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