xref: /netbsd-src/external/mit/libuv/dist/docs/src/guide/basics.rst (revision 5f2f42719cd62ff11fd913b40b7ce19f07c4fd25)
10e552da7SchristosBasics of libuv
20e552da7Schristos===============
30e552da7Schristos
40e552da7Schristoslibuv enforces an **asynchronous**, **event-driven** style of programming.  Its
50e552da7Schristoscore job is to provide an event loop and callback based notifications of I/O
60e552da7Schristosand other activities.  libuv offers core utilities like timers, non-blocking
70e552da7Schristosnetworking support, asynchronous file system access, child processes and more.
80e552da7Schristos
90e552da7SchristosEvent loops
100e552da7Schristos-----------
110e552da7Schristos
120e552da7SchristosIn event-driven programming, an application expresses interest in certain events
130e552da7Schristosand respond to them when they occur. The responsibility of gathering events
140e552da7Schristosfrom the operating system or monitoring other sources of events is handled by
150e552da7Schristoslibuv, and the user can register callbacks to be invoked when an event occurs.
160e552da7SchristosThe event-loop usually keeps running *forever*. In pseudocode:
170e552da7Schristos
180e552da7Schristos.. code-block:: python
190e552da7Schristos
200e552da7Schristos    while there are still events to process:
210e552da7Schristos        e = get the next event
220e552da7Schristos        if there is a callback associated with e:
230e552da7Schristos            call the callback
240e552da7Schristos
250e552da7SchristosSome examples of events are:
260e552da7Schristos
270e552da7Schristos* File is ready for writing
280e552da7Schristos* A socket has data ready to be read
290e552da7Schristos* A timer has timed out
300e552da7Schristos
310e552da7SchristosThis event loop is encapsulated by ``uv_run()`` -- the end-all function when using
320e552da7Schristoslibuv.
330e552da7Schristos
340e552da7SchristosThe most common activity of systems programs is to deal with input and output,
350e552da7Schristosrather than a lot of number-crunching. The problem with using conventional
360e552da7Schristosinput/output functions (``read``, ``fprintf``, etc.) is that they are
370e552da7Schristos**blocking**. The actual write to a hard disk or reading from a network, takes
380e552da7Schristosa disproportionately long time compared to the speed of the processor. The
390e552da7Schristosfunctions don't return until the task is done, so that your program is doing
400e552da7Schristosnothing. For programs which require high performance this is a major roadblock
410e552da7Schristosas other activities and other I/O operations are kept waiting.
420e552da7Schristos
430e552da7SchristosOne of the standard solutions is to use threads. Each blocking I/O operation is
440e552da7Schristosstarted in a separate thread (or in a thread pool). When the blocking function
45*5f2f4271Schristosgets invoked in the thread, the operating system can schedule another thread to run,
460e552da7Schristoswhich actually needs the CPU.
470e552da7Schristos
480e552da7SchristosThe approach followed by libuv uses another style, which is the **asynchronous,
490e552da7Schristosnon-blocking** style. Most modern operating systems provide event notification
500e552da7Schristossubsystems. For example, a normal ``read`` call on a socket would block until
510e552da7Schristosthe sender actually sent something. Instead, the application can request the
520e552da7Schristosoperating system to watch the socket and put an event notification in the
530e552da7Schristosqueue. The application can inspect the events at its convenience (perhaps doing
540e552da7Schristossome number crunching before to use the processor to the maximum) and grab the
550e552da7Schristosdata. It is **asynchronous** because the application expressed interest at one
560e552da7Schristospoint, then used the data at another point (in time and space). It is
570e552da7Schristos**non-blocking** because the application process was free to do other tasks.
580e552da7SchristosThis fits in well with libuv's event-loop approach, since the operating system
590e552da7Schristosevents can be treated as just another libuv event. The non-blocking ensures
600e552da7Schristosthat other events can continue to be handled as fast as they come in [#]_.
610e552da7Schristos
620e552da7Schristos.. NOTE::
630e552da7Schristos
640e552da7Schristos    How the I/O is run in the background is not of our concern, but due to the
650e552da7Schristos    way our computer hardware works, with the thread as the basic unit of the
660e552da7Schristos    processor, libuv and OSes will usually run background/worker threads and/or
670e552da7Schristos    polling to perform tasks in a non-blocking manner.
680e552da7Schristos
690e552da7SchristosBert Belder, one of the libuv core developers has a small video explaining the
700e552da7Schristosarchitecture of libuv and its background. If you have no prior experience with
710e552da7Schristoseither libuv or libev, it is a quick, useful watch.
720e552da7Schristos
730e552da7Schristoslibuv's event loop is explained in more detail in the `documentation
74*5f2f4271Schristos<https://docs.libuv.org/en/v1.x/design.html#the-i-o-loop>`_.
750e552da7Schristos
760e552da7Schristos.. raw:: html
770e552da7Schristos
780e552da7Schristos    <iframe width="560" height="315"
790e552da7Schristos    src="https://www.youtube-nocookie.com/embed/nGn60vDSxQ4" frameborder="0"
800e552da7Schristos    allowfullscreen></iframe>
810e552da7Schristos
820e552da7SchristosHello World
830e552da7Schristos-----------
840e552da7Schristos
850e552da7SchristosWith the basics out of the way, let's write our first libuv program. It does
860e552da7Schristosnothing, except start a loop which will exit immediately.
870e552da7Schristos
880e552da7Schristos.. rubric:: helloworld/main.c
890e552da7Schristos.. literalinclude:: ../../code/helloworld/main.c
90*5f2f4271Schristos    :language: c
910e552da7Schristos    :linenos:
920e552da7Schristos
930e552da7SchristosThis program quits immediately because it has no events to process. A libuv
940e552da7Schristosevent loop has to be told to watch out for events using the various API
950e552da7Schristosfunctions.
960e552da7Schristos
970e552da7SchristosStarting with libuv v1.0, users should allocate the memory for the loops before
980e552da7Schristosinitializing it with ``uv_loop_init(uv_loop_t *)``. This allows you to plug in
990e552da7Schristoscustom memory management. Remember to de-initialize the loop using
1000e552da7Schristos``uv_loop_close(uv_loop_t *)`` and then delete the storage. The examples never
1010e552da7Schristosclose loops since the program quits after the loop ends and the system will
1020e552da7Schristosreclaim memory. Production grade projects, especially long running systems
1030e552da7Schristosprograms, should take care to release correctly.
1040e552da7Schristos
1050e552da7SchristosDefault loop
1060e552da7Schristos++++++++++++
1070e552da7Schristos
1080e552da7SchristosA default loop is provided by libuv and can be accessed using
1090e552da7Schristos``uv_default_loop()``. You should use this loop if you only want a single
1100e552da7Schristosloop.
1110e552da7Schristos
112*5f2f4271Schristos.. rubric:: default-loop/main.c
113*5f2f4271Schristos.. literalinclude:: ../../code/default-loop/main.c
114*5f2f4271Schristos    :language: c
115*5f2f4271Schristos    :linenos:
116*5f2f4271Schristos
1170e552da7Schristos.. note::
1180e552da7Schristos
1190e552da7Schristos    node.js uses the default loop as its main loop. If you are writing bindings
1200e552da7Schristos    you should be aware of this.
1210e552da7Schristos
1220e552da7Schristos.. _libuv-error-handling:
1230e552da7Schristos
1240e552da7SchristosError handling
1250e552da7Schristos--------------
1260e552da7Schristos
1270e552da7SchristosInitialization functions or synchronous functions which may fail return a negative number on error. Async functions that may fail will pass a status parameter to their callbacks. The error messages are defined as ``UV_E*`` `constants`_.
1280e552da7Schristos
129*5f2f4271Schristos.. _constants: https://docs.libuv.org/en/v1.x/errors.html#error-constants
1300e552da7Schristos
1310e552da7SchristosYou can use the ``uv_strerror(int)`` and ``uv_err_name(int)`` functions
1320e552da7Schristosto get a ``const char *`` describing the error or the error name respectively.
1330e552da7Schristos
1340e552da7SchristosI/O read callbacks (such as for files and sockets) are passed a parameter ``nread``. If ``nread`` is less than 0, there was an error (UV_EOF is the end of file error, which you may want to handle differently).
1350e552da7Schristos
1360e552da7SchristosHandles and Requests
1370e552da7Schristos--------------------
1380e552da7Schristos
1390e552da7Schristoslibuv works by the user expressing interest in particular events. This is
1400e552da7Schristosusually done by creating a **handle** to an I/O device, timer or process.
1410e552da7SchristosHandles are opaque structs named as ``uv_TYPE_t`` where type signifies what the
1420e552da7Schristoshandle is used for.
1430e552da7Schristos
1440e552da7Schristos.. rubric:: libuv watchers
1450e552da7Schristos.. code-block:: c
1460e552da7Schristos
1470e552da7Schristos    /* Handle types. */
1480e552da7Schristos    typedef struct uv_loop_s uv_loop_t;
1490e552da7Schristos    typedef struct uv_handle_s uv_handle_t;
1500e552da7Schristos    typedef struct uv_dir_s uv_dir_t;
1510e552da7Schristos    typedef struct uv_stream_s uv_stream_t;
1520e552da7Schristos    typedef struct uv_tcp_s uv_tcp_t;
1530e552da7Schristos    typedef struct uv_udp_s uv_udp_t;
1540e552da7Schristos    typedef struct uv_pipe_s uv_pipe_t;
1550e552da7Schristos    typedef struct uv_tty_s uv_tty_t;
1560e552da7Schristos    typedef struct uv_poll_s uv_poll_t;
1570e552da7Schristos    typedef struct uv_timer_s uv_timer_t;
1580e552da7Schristos    typedef struct uv_prepare_s uv_prepare_t;
1590e552da7Schristos    typedef struct uv_check_s uv_check_t;
1600e552da7Schristos    typedef struct uv_idle_s uv_idle_t;
1610e552da7Schristos    typedef struct uv_async_s uv_async_t;
1620e552da7Schristos    typedef struct uv_process_s uv_process_t;
1630e552da7Schristos    typedef struct uv_fs_event_s uv_fs_event_t;
1640e552da7Schristos    typedef struct uv_fs_poll_s uv_fs_poll_t;
1650e552da7Schristos    typedef struct uv_signal_s uv_signal_t;
1660e552da7Schristos
1670e552da7Schristos    /* Request types. */
1680e552da7Schristos    typedef struct uv_req_s uv_req_t;
1690e552da7Schristos    typedef struct uv_getaddrinfo_s uv_getaddrinfo_t;
1700e552da7Schristos    typedef struct uv_getnameinfo_s uv_getnameinfo_t;
1710e552da7Schristos    typedef struct uv_shutdown_s uv_shutdown_t;
1720e552da7Schristos    typedef struct uv_write_s uv_write_t;
1730e552da7Schristos    typedef struct uv_connect_s uv_connect_t;
1740e552da7Schristos    typedef struct uv_udp_send_s uv_udp_send_t;
1750e552da7Schristos    typedef struct uv_fs_s uv_fs_t;
1760e552da7Schristos    typedef struct uv_work_s uv_work_t;
177*5f2f4271Schristos    typedef struct uv_random_s uv_random_t;
178*5f2f4271Schristos
179*5f2f4271Schristos    /* None of the above. */
180*5f2f4271Schristos    typedef struct uv_env_item_s uv_env_item_t;
181*5f2f4271Schristos    typedef struct uv_cpu_info_s uv_cpu_info_t;
182*5f2f4271Schristos    typedef struct uv_interface_address_s uv_interface_address_t;
183*5f2f4271Schristos    typedef struct uv_dirent_s uv_dirent_t;
184*5f2f4271Schristos    typedef struct uv_passwd_s uv_passwd_t;
185*5f2f4271Schristos    typedef struct uv_utsname_s uv_utsname_t;
186*5f2f4271Schristos    typedef struct uv_statfs_s uv_statfs_t;
1870e552da7Schristos
1880e552da7Schristos
1890e552da7SchristosHandles represent long-lived objects. Async operations on such handles are
1900e552da7Schristosidentified using **requests**. A request is short-lived (usually used across
1910e552da7Schristosonly one callback) and usually indicates one I/O operation on a handle.
1920e552da7SchristosRequests are used to preserve context between the initiation and the callback
1930e552da7Schristosof individual actions. For example, an UDP socket is represented by
1940e552da7Schristosa ``uv_udp_t``, while individual writes to the socket use a ``uv_udp_send_t``
1950e552da7Schristosstructure that is passed to the callback after the write is done.
1960e552da7Schristos
1970e552da7SchristosHandles are setup by a corresponding::
1980e552da7Schristos
1990e552da7Schristos    uv_TYPE_init(uv_loop_t *, uv_TYPE_t *)
2000e552da7Schristos
2010e552da7Schristosfunction.
2020e552da7Schristos
2030e552da7SchristosCallbacks are functions which are called by libuv whenever an event the watcher
2040e552da7Schristosis interested in has taken place. Application specific logic will usually be
2050e552da7Schristosimplemented in the callback. For example, an IO watcher's callback will receive
2060e552da7Schristosthe data read from a file, a timer callback will be triggered on timeout and so
2070e552da7Schristoson.
2080e552da7Schristos
2090e552da7SchristosIdling
2100e552da7Schristos++++++
2110e552da7Schristos
2120e552da7SchristosHere is an example of using an idle handle. The callback is called once on
2130e552da7Schristosevery turn of the event loop. A use case for idle handles is discussed in
2140e552da7Schristos:doc:`utilities`. Let us use an idle watcher to look at the watcher life cycle
2150e552da7Schristosand see how ``uv_run()`` will now block because a watcher is present. The idle
2160e552da7Schristoswatcher is stopped when the count is reached and ``uv_run()`` exits since no
2170e552da7Schristosevent watchers are active.
2180e552da7Schristos
2190e552da7Schristos.. rubric:: idle-basic/main.c
2200e552da7Schristos.. literalinclude:: ../../code/idle-basic/main.c
221*5f2f4271Schristos    :language: c
2220e552da7Schristos    :emphasize-lines: 6,10,14-17
2230e552da7Schristos
2240e552da7SchristosStoring context
2250e552da7Schristos+++++++++++++++
2260e552da7Schristos
2270e552da7SchristosIn callback based programming style you'll often want to pass some 'context' --
2280e552da7Schristosapplication specific information -- between the call site and the callback. All
2290e552da7Schristoshandles and requests have a ``void* data`` member which you can set to the
2300e552da7Schristoscontext and cast back in the callback. This is a common pattern used throughout
2310e552da7Schristosthe C library ecosystem. In addition ``uv_loop_t`` also has a similar data
2320e552da7Schristosmember.
2330e552da7Schristos
2340e552da7Schristos----
2350e552da7Schristos
2360e552da7Schristos.. [#] Depending on the capacity of the hardware of course.
237