Alien-uv
view release on metacpan or search on metacpan
libuv/docs/src/guide/utilities.rst view on Meta::CPAN
``start_timeout`` will be called immediately the first time by libcurl, so
things are set in motion. This simply starts a libuv `timer <Timers>`_ which
drives ``curl_multi_socket_action`` with ``CURL_SOCKET_TIMEOUT`` whenever it
times out. ``curl_multi_socket_action`` is what drives libcurl, and what we
call whenever sockets change state. But before we go into that, we need to poll
on sockets whenever ``handle_socket`` is called.
.. rubric:: uvwget/main.c - Setting up polling
.. literalinclude:: ../../code/uvwget/main.c
:linenos:
:lines: 102-140
:emphasize-lines: 9,11,15,21,24
We are interested in the socket fd ``s``, and the ``action``. For every socket
we create a ``uv_poll_t`` handle if it doesn't exist, and associate it with the
socket using ``curl_multi_assign``. This way ``socketp`` points to it whenever
the callback is invoked.
In the case that the download is done or fails, libcurl requests removal of the
poll. So we stop and free the poll handle.
Depending on what events libcurl wishes to watch for, we start polling with
``UV_READABLE`` or ``UV_WRITABLE``. Now libuv will invoke the poll callback
whenever the socket is ready for reading or writing. Calling ``uv_poll_start``
multiple times on the same handle is acceptable, it will just update the events
mask with the new value. ``curl_perform`` is the crux of this program.
.. rubric:: uvwget/main.c - Driving libcurl.
.. literalinclude:: ../../code/uvwget/main.c
:linenos:
:lines: 81-95
:emphasize-lines: 2,6-7,12
The first thing we do is to stop the timer, since there has been some progress
in the interval. Then depending on what event triggered the callback, we set
the correct flags. Then we call ``curl_multi_socket_action`` with the socket
that progressed and the flags informing about what events happened. At this
point libcurl does all of its internal tasks in small increments, and will
attempt to return as fast as possible, which is exactly what an evented program
wants in its main thread. libcurl keeps queueing messages into its own queue
about transfer progress. In our case we are only interested in transfers that
are completed. So we extract these messages, and clean up handles whose
transfers are done.
.. rubric:: uvwget/main.c - Reading transfer status.
.. literalinclude:: ../../code/uvwget/main.c
:linenos:
:lines: 58-79
:emphasize-lines: 6,9-10,13-14
Check & Prepare watchers
------------------------
TODO
Loading libraries
-----------------
libuv provides a cross platform API to dynamically load `shared libraries`_.
This can be used to implement your own plugin/extension/module system and is
used by node.js to implement ``require()`` support for bindings. The usage is
quite simple as long as your library exports the right symbols. Be careful with
sanity and security checks when loading third party code, otherwise your
program will behave unpredictably. This example implements a very simple
plugin system which does nothing except print the name of the plugin.
Let us first look at the interface provided to plugin authors.
.. rubric:: plugin/plugin.h
.. literalinclude:: ../../code/plugin/plugin.h
:linenos:
You can similarly add more functions that plugin authors can use to do useful
things in your application [#]_. A sample plugin using this API is:
.. rubric:: plugin/hello.c
.. literalinclude:: ../../code/plugin/hello.c
:linenos:
Our interface defines that all plugins should have an ``initialize`` function
which will be called by the application. This plugin is compiled as a shared
library and can be loaded by running our application::
$ ./plugin libhello.dylib
Loading libhello.dylib
Registered plugin "Hello World!"
.. NOTE::
The shared library filename will be different depending on platforms. On
Linux it is ``libhello.so``.
This is done by using ``uv_dlopen`` to first load the shared library
``libhello.dylib``. Then we get access to the ``initialize`` function using
``uv_dlsym`` and invoke it.
.. rubric:: plugin/main.c
.. literalinclude:: ../../code/plugin/main.c
:linenos:
:lines: 7-
:emphasize-lines: 15, 18, 24
``uv_dlopen`` expects a path to the shared library and sets the opaque
``uv_lib_t`` pointer. It returns 0 on success, -1 on error. Use ``uv_dlerror``
to get the error message.
``uv_dlsym`` stores a pointer to the symbol in the second argument in the third
argument. ``init_plugin_function`` is a function pointer to the sort of
function we are looking for in the application's plugins.
.. _shared libraries: http://en.wikipedia.org/wiki/Shared_library#Shared_libraries
TTY
---
Text terminals have supported basic formatting for a long time, with a `pretty
standardised`_ command set. This formatting is often used by programs to
improve the readability of terminal output. For example ``grep --colour``.
libuv provides the ``uv_tty_t`` abstraction (a stream) and related functions to
implement the ANSI escape codes across all platforms. By this I mean that libuv
converts ANSI codes to the Windows equivalent, and provides functions to get
libuv/docs/src/guide/utilities.rst view on Meta::CPAN
int uv_tty_init(uv_loop_t*, uv_tty_t*, uv_file fd, int unused)
The ``unused`` parameter is now auto-detected and ignored. It previously needed
to be set to use ``uv_read_start()`` on the stream.
It is then best to use ``uv_tty_set_mode`` to set the mode to *normal*
which enables most TTY formatting, flow-control and other settings. Other_ modes
are also available.
.. _Other: http://docs.libuv.org/en/v1.x/tty.html#c.uv_tty_mode_t
Remember to call ``uv_tty_reset_mode`` when your program exits to restore the
state of the terminal. Just good manners. Another set of good manners is to be
aware of redirection. If the user redirects the output of your command to
a file, control sequences should not be written as they impede readability and
``grep``. To check if the file descriptor is indeed a TTY, call
``uv_guess_handle`` with the file descriptor and compare the return value with
``UV_TTY``.
Here is a simple example which prints white text on a red background:
.. rubric:: tty/main.c
.. literalinclude:: ../../code/tty/main.c
:linenos:
:emphasize-lines: 11-12,14,17,27
The final TTY helper is ``uv_tty_get_winsize()`` which is used to get the
width and height of the terminal and returns ``0`` on success. Here is a small
program which does some animation using the function and character position
escape codes.
.. rubric:: tty-gravity/main.c
.. literalinclude:: ../../code/tty-gravity/main.c
:linenos:
:emphasize-lines: 19,25,38
The escape codes are:
====== =======================
Code Meaning
====== =======================
*2* J Clear part of the screen, 2 is entire screen
H Moves cursor to certain position, default top-left
*n* B Moves cursor down by n lines
*n* C Moves cursor right by n columns
m Obeys string of display settings, in this case green background (40+2), white text (30+7)
====== =======================
As you can see this is very useful to produce nicely formatted output, or even
console based arcade games if that tickles your fancy. For fancier control you
can try `ncurses`_.
.. _ncurses: http://www.gnu.org/software/ncurses/ncurses.html
.. versionchanged:: 1.23.1: the `readable` parameter is now unused and ignored.
The appropriate value will now be auto-detected from the kernel.
----
.. [#] I was first introduced to the term baton in this context, in Konstantin
Käfer's excellent slides on writing node.js bindings --
http://kkaefer.github.com/node-cpp-modules/#baton
.. [#] mfp is My Fancy Plugin
.. _libev man page: http://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod#COMMON_OR_USEFUL_IDIOMS_OR_BOTH
( run in 1.571 second using v1.01-cache-2.11-cpan-59e3e3084b8 )