1e66f31c5Sopenharmony_ciBasics of libuv
2e66f31c5Sopenharmony_ci===============
3e66f31c5Sopenharmony_ci
4e66f31c5Sopenharmony_cilibuv enforces an **asynchronous**, **event-driven** style of programming.  Its
5e66f31c5Sopenharmony_cicore job is to provide an event loop and callback based notifications of I/O
6e66f31c5Sopenharmony_ciand other activities.  libuv offers core utilities like timers, non-blocking
7e66f31c5Sopenharmony_cinetworking support, asynchronous file system access, child processes and more.
8e66f31c5Sopenharmony_ci
9e66f31c5Sopenharmony_ciEvent loops
10e66f31c5Sopenharmony_ci-----------
11e66f31c5Sopenharmony_ci
12e66f31c5Sopenharmony_ciIn event-driven programming, an application expresses interest in certain events
13e66f31c5Sopenharmony_ciand respond to them when they occur. The responsibility of gathering events
14e66f31c5Sopenharmony_cifrom the operating system or monitoring other sources of events is handled by
15e66f31c5Sopenharmony_cilibuv, and the user can register callbacks to be invoked when an event occurs.
16e66f31c5Sopenharmony_ciThe event-loop usually keeps running *forever*. In pseudocode:
17e66f31c5Sopenharmony_ci
18e66f31c5Sopenharmony_ci.. code-block:: python
19e66f31c5Sopenharmony_ci
20e66f31c5Sopenharmony_ci    while there are still events to process:
21e66f31c5Sopenharmony_ci        e = get the next event
22e66f31c5Sopenharmony_ci        if there is a callback associated with e:
23e66f31c5Sopenharmony_ci            call the callback
24e66f31c5Sopenharmony_ci
25e66f31c5Sopenharmony_ciSome examples of events are:
26e66f31c5Sopenharmony_ci
27e66f31c5Sopenharmony_ci* File is ready for writing
28e66f31c5Sopenharmony_ci* A socket has data ready to be read
29e66f31c5Sopenharmony_ci* A timer has timed out
30e66f31c5Sopenharmony_ci
31e66f31c5Sopenharmony_ciThis event loop is encapsulated by ``uv_run()`` -- the end-all function when using
32e66f31c5Sopenharmony_cilibuv.
33e66f31c5Sopenharmony_ci
34e66f31c5Sopenharmony_ciThe most common activity of systems programs is to deal with input and output,
35e66f31c5Sopenharmony_cirather than a lot of number-crunching. The problem with using conventional
36e66f31c5Sopenharmony_ciinput/output functions (``read``, ``fprintf``, etc.) is that they are
37e66f31c5Sopenharmony_ci**blocking**. The actual write to a hard disk or reading from a network, takes
38e66f31c5Sopenharmony_cia disproportionately long time compared to the speed of the processor. The
39e66f31c5Sopenharmony_cifunctions don't return until the task is done, so that your program is doing
40e66f31c5Sopenharmony_cinothing. For programs which require high performance this is a major roadblock
41e66f31c5Sopenharmony_cias other activities and other I/O operations are kept waiting.
42e66f31c5Sopenharmony_ci
43e66f31c5Sopenharmony_ciOne of the standard solutions is to use threads. Each blocking I/O operation is
44e66f31c5Sopenharmony_cistarted in a separate thread (or in a thread pool). When the blocking function
45e66f31c5Sopenharmony_cigets invoked in the thread, the operating system can schedule another thread to run,
46e66f31c5Sopenharmony_ciwhich actually needs the CPU.
47e66f31c5Sopenharmony_ci
48e66f31c5Sopenharmony_ciThe approach followed by libuv uses another style, which is the **asynchronous,
49e66f31c5Sopenharmony_cinon-blocking** style. Most modern operating systems provide event notification
50e66f31c5Sopenharmony_cisubsystems. For example, a normal ``read`` call on a socket would block until
51e66f31c5Sopenharmony_cithe sender actually sent something. Instead, the application can request the
52e66f31c5Sopenharmony_cioperating system to watch the socket and put an event notification in the
53e66f31c5Sopenharmony_ciqueue. The application can inspect the events at its convenience (perhaps doing
54e66f31c5Sopenharmony_cisome number crunching before to use the processor to the maximum) and grab the
55e66f31c5Sopenharmony_cidata. It is **asynchronous** because the application expressed interest at one
56e66f31c5Sopenharmony_cipoint, then used the data at another point (in time and space). It is
57e66f31c5Sopenharmony_ci**non-blocking** because the application process was free to do other tasks.
58e66f31c5Sopenharmony_ciThis fits in well with libuv's event-loop approach, since the operating system
59e66f31c5Sopenharmony_cievents can be treated as just another libuv event. The non-blocking ensures
60e66f31c5Sopenharmony_cithat other events can continue to be handled as fast as they come in [#]_.
61e66f31c5Sopenharmony_ci
62e66f31c5Sopenharmony_ci.. NOTE::
63e66f31c5Sopenharmony_ci
64e66f31c5Sopenharmony_ci    How the I/O is run in the background is not of our concern, but due to the
65e66f31c5Sopenharmony_ci    way our computer hardware works, with the thread as the basic unit of the
66e66f31c5Sopenharmony_ci    processor, libuv and OSes will usually run background/worker threads and/or
67e66f31c5Sopenharmony_ci    polling to perform tasks in a non-blocking manner.
68e66f31c5Sopenharmony_ci
69e66f31c5Sopenharmony_ciBert Belder, one of the libuv core developers has a small video explaining the
70e66f31c5Sopenharmony_ciarchitecture of libuv and its background. If you have no prior experience with
71e66f31c5Sopenharmony_cieither libuv or libev, it is a quick, useful watch.
72e66f31c5Sopenharmony_ci
73e66f31c5Sopenharmony_cilibuv's event loop is explained in more detail in the `documentation
74e66f31c5Sopenharmony_ci<https://docs.libuv.org/en/v1.x/design.html#the-i-o-loop>`_.
75e66f31c5Sopenharmony_ci
76e66f31c5Sopenharmony_ci.. raw:: html
77e66f31c5Sopenharmony_ci
78e66f31c5Sopenharmony_ci    <iframe width="560" height="315"
79e66f31c5Sopenharmony_ci    src="https://www.youtube-nocookie.com/embed/nGn60vDSxQ4" frameborder="0"
80e66f31c5Sopenharmony_ci    allowfullscreen></iframe>
81e66f31c5Sopenharmony_ci
82e66f31c5Sopenharmony_ciHello World
83e66f31c5Sopenharmony_ci-----------
84e66f31c5Sopenharmony_ci
85e66f31c5Sopenharmony_ciWith the basics out of the way, let's write our first libuv program. It does
86e66f31c5Sopenharmony_cinothing, except start a loop which will exit immediately.
87e66f31c5Sopenharmony_ci
88e66f31c5Sopenharmony_ci.. rubric:: helloworld/main.c
89e66f31c5Sopenharmony_ci.. literalinclude:: ../../code/helloworld/main.c
90e66f31c5Sopenharmony_ci    :language: c
91e66f31c5Sopenharmony_ci    :linenos:
92e66f31c5Sopenharmony_ci
93e66f31c5Sopenharmony_ciThis program quits immediately because it has no events to process. A libuv
94e66f31c5Sopenharmony_cievent loop has to be told to watch out for events using the various API
95e66f31c5Sopenharmony_cifunctions.
96e66f31c5Sopenharmony_ci
97e66f31c5Sopenharmony_ciStarting with libuv v1.0, users should allocate the memory for the loops before
98e66f31c5Sopenharmony_ciinitializing it with ``uv_loop_init(uv_loop_t *)``. This allows you to plug in
99e66f31c5Sopenharmony_cicustom memory management. Remember to de-initialize the loop using
100e66f31c5Sopenharmony_ci``uv_loop_close(uv_loop_t *)`` and then delete the storage. The examples never
101e66f31c5Sopenharmony_ciclose loops since the program quits after the loop ends and the system will
102e66f31c5Sopenharmony_cireclaim memory. Production grade projects, especially long running systems
103e66f31c5Sopenharmony_ciprograms, should take care to release correctly.
104e66f31c5Sopenharmony_ci
105e66f31c5Sopenharmony_ciDefault loop
106e66f31c5Sopenharmony_ci++++++++++++
107e66f31c5Sopenharmony_ci
108e66f31c5Sopenharmony_ciA default loop is provided by libuv and can be accessed using
109e66f31c5Sopenharmony_ci``uv_default_loop()``. You should use this loop if you only want a single
110e66f31c5Sopenharmony_ciloop.
111e66f31c5Sopenharmony_ci
112e66f31c5Sopenharmony_ci.. rubric:: default-loop/main.c
113e66f31c5Sopenharmony_ci.. literalinclude:: ../../code/default-loop/main.c
114e66f31c5Sopenharmony_ci    :language: c
115e66f31c5Sopenharmony_ci    :linenos:
116e66f31c5Sopenharmony_ci
117e66f31c5Sopenharmony_ci.. note::
118e66f31c5Sopenharmony_ci
119e66f31c5Sopenharmony_ci    node.js uses the default loop as its main loop. If you are writing bindings
120e66f31c5Sopenharmony_ci    you should be aware of this.
121e66f31c5Sopenharmony_ci
122e66f31c5Sopenharmony_ci.. _libuv-error-handling:
123e66f31c5Sopenharmony_ci
124e66f31c5Sopenharmony_ciError handling
125e66f31c5Sopenharmony_ci--------------
126e66f31c5Sopenharmony_ci
127e66f31c5Sopenharmony_ciInitialization 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`_.
128e66f31c5Sopenharmony_ci
129e66f31c5Sopenharmony_ci.. _constants: https://docs.libuv.org/en/v1.x/errors.html#error-constants
130e66f31c5Sopenharmony_ci
131e66f31c5Sopenharmony_ciYou can use the ``uv_strerror(int)`` and ``uv_err_name(int)`` functions
132e66f31c5Sopenharmony_cito get a ``const char *`` describing the error or the error name respectively.
133e66f31c5Sopenharmony_ci
134e66f31c5Sopenharmony_ciI/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).
135e66f31c5Sopenharmony_ci
136e66f31c5Sopenharmony_ciHandles and Requests
137e66f31c5Sopenharmony_ci--------------------
138e66f31c5Sopenharmony_ci
139e66f31c5Sopenharmony_cilibuv works by the user expressing interest in particular events. This is
140e66f31c5Sopenharmony_ciusually done by creating a **handle** to an I/O device, timer or process.
141e66f31c5Sopenharmony_ciHandles are opaque structs named as ``uv_TYPE_t`` where type signifies what the
142e66f31c5Sopenharmony_cihandle is used for.
143e66f31c5Sopenharmony_ci
144e66f31c5Sopenharmony_ci.. rubric:: libuv watchers
145e66f31c5Sopenharmony_ci.. code-block:: c
146e66f31c5Sopenharmony_ci
147e66f31c5Sopenharmony_ci    /* Handle types. */
148e66f31c5Sopenharmony_ci    typedef struct uv_loop_s uv_loop_t;
149e66f31c5Sopenharmony_ci    typedef struct uv_handle_s uv_handle_t;
150e66f31c5Sopenharmony_ci    typedef struct uv_dir_s uv_dir_t;
151e66f31c5Sopenharmony_ci    typedef struct uv_stream_s uv_stream_t;
152e66f31c5Sopenharmony_ci    typedef struct uv_tcp_s uv_tcp_t;
153e66f31c5Sopenharmony_ci    typedef struct uv_udp_s uv_udp_t;
154e66f31c5Sopenharmony_ci    typedef struct uv_pipe_s uv_pipe_t;
155e66f31c5Sopenharmony_ci    typedef struct uv_tty_s uv_tty_t;
156e66f31c5Sopenharmony_ci    typedef struct uv_poll_s uv_poll_t;
157e66f31c5Sopenharmony_ci    typedef struct uv_timer_s uv_timer_t;
158e66f31c5Sopenharmony_ci    typedef struct uv_prepare_s uv_prepare_t;
159e66f31c5Sopenharmony_ci    typedef struct uv_check_s uv_check_t;
160e66f31c5Sopenharmony_ci    typedef struct uv_idle_s uv_idle_t;
161e66f31c5Sopenharmony_ci    typedef struct uv_async_s uv_async_t;
162e66f31c5Sopenharmony_ci    typedef struct uv_process_s uv_process_t;
163e66f31c5Sopenharmony_ci    typedef struct uv_fs_event_s uv_fs_event_t;
164e66f31c5Sopenharmony_ci    typedef struct uv_fs_poll_s uv_fs_poll_t;
165e66f31c5Sopenharmony_ci    typedef struct uv_signal_s uv_signal_t;
166e66f31c5Sopenharmony_ci
167e66f31c5Sopenharmony_ci    /* Request types. */
168e66f31c5Sopenharmony_ci    typedef struct uv_req_s uv_req_t;
169e66f31c5Sopenharmony_ci    typedef struct uv_getaddrinfo_s uv_getaddrinfo_t;
170e66f31c5Sopenharmony_ci    typedef struct uv_getnameinfo_s uv_getnameinfo_t;
171e66f31c5Sopenharmony_ci    typedef struct uv_shutdown_s uv_shutdown_t;
172e66f31c5Sopenharmony_ci    typedef struct uv_write_s uv_write_t;
173e66f31c5Sopenharmony_ci    typedef struct uv_connect_s uv_connect_t;
174e66f31c5Sopenharmony_ci    typedef struct uv_udp_send_s uv_udp_send_t;
175e66f31c5Sopenharmony_ci    typedef struct uv_fs_s uv_fs_t;
176e66f31c5Sopenharmony_ci    typedef struct uv_work_s uv_work_t;
177e66f31c5Sopenharmony_ci    typedef struct uv_random_s uv_random_t;
178e66f31c5Sopenharmony_ci
179e66f31c5Sopenharmony_ci    /* None of the above. */
180e66f31c5Sopenharmony_ci    typedef struct uv_env_item_s uv_env_item_t;
181e66f31c5Sopenharmony_ci    typedef struct uv_cpu_info_s uv_cpu_info_t;
182e66f31c5Sopenharmony_ci    typedef struct uv_interface_address_s uv_interface_address_t;
183e66f31c5Sopenharmony_ci    typedef struct uv_dirent_s uv_dirent_t;
184e66f31c5Sopenharmony_ci    typedef struct uv_passwd_s uv_passwd_t;
185e66f31c5Sopenharmony_ci    typedef struct uv_utsname_s uv_utsname_t;
186e66f31c5Sopenharmony_ci    typedef struct uv_statfs_s uv_statfs_t;
187e66f31c5Sopenharmony_ci
188e66f31c5Sopenharmony_ci
189e66f31c5Sopenharmony_ciHandles represent long-lived objects. Async operations on such handles are
190e66f31c5Sopenharmony_ciidentified using **requests**. A request is short-lived (usually used across
191e66f31c5Sopenharmony_cionly one callback) and usually indicates one I/O operation on a handle.
192e66f31c5Sopenharmony_ciRequests are used to preserve context between the initiation and the callback
193e66f31c5Sopenharmony_ciof individual actions. For example, an UDP socket is represented by
194e66f31c5Sopenharmony_cia ``uv_udp_t``, while individual writes to the socket use a ``uv_udp_send_t``
195e66f31c5Sopenharmony_cistructure that is passed to the callback after the write is done.
196e66f31c5Sopenharmony_ci
197e66f31c5Sopenharmony_ciHandles are setup by a corresponding::
198e66f31c5Sopenharmony_ci
199e66f31c5Sopenharmony_ci    uv_TYPE_init(uv_loop_t *, uv_TYPE_t *)
200e66f31c5Sopenharmony_ci
201e66f31c5Sopenharmony_cifunction.
202e66f31c5Sopenharmony_ci
203e66f31c5Sopenharmony_ciCallbacks are functions which are called by libuv whenever an event the watcher
204e66f31c5Sopenharmony_ciis interested in has taken place. Application specific logic will usually be
205e66f31c5Sopenharmony_ciimplemented in the callback. For example, an IO watcher's callback will receive
206e66f31c5Sopenharmony_cithe data read from a file, a timer callback will be triggered on timeout and so
207e66f31c5Sopenharmony_cion.
208e66f31c5Sopenharmony_ci
209e66f31c5Sopenharmony_ciIdling
210e66f31c5Sopenharmony_ci++++++
211e66f31c5Sopenharmony_ci
212e66f31c5Sopenharmony_ciHere is an example of using an idle handle. The callback is called once on
213e66f31c5Sopenharmony_cievery turn of the event loop. A use case for idle handles is discussed in
214e66f31c5Sopenharmony_ci:doc:`utilities`. Let us use an idle watcher to look at the watcher life cycle
215e66f31c5Sopenharmony_ciand see how ``uv_run()`` will now block because a watcher is present. The idle
216e66f31c5Sopenharmony_ciwatcher is stopped when the count is reached and ``uv_run()`` exits since no
217e66f31c5Sopenharmony_cievent watchers are active.
218e66f31c5Sopenharmony_ci
219e66f31c5Sopenharmony_ci.. rubric:: idle-basic/main.c
220e66f31c5Sopenharmony_ci.. literalinclude:: ../../code/idle-basic/main.c
221e66f31c5Sopenharmony_ci    :language: c
222e66f31c5Sopenharmony_ci    :emphasize-lines: 6,10,14-17
223e66f31c5Sopenharmony_ci
224e66f31c5Sopenharmony_ciStoring context
225e66f31c5Sopenharmony_ci+++++++++++++++
226e66f31c5Sopenharmony_ci
227e66f31c5Sopenharmony_ciIn callback based programming style you'll often want to pass some 'context' --
228e66f31c5Sopenharmony_ciapplication specific information -- between the call site and the callback. All
229e66f31c5Sopenharmony_cihandles and requests have a ``void* data`` member which you can set to the
230e66f31c5Sopenharmony_cicontext and cast back in the callback. This is a common pattern used throughout
231e66f31c5Sopenharmony_cithe C library ecosystem. In addition ``uv_loop_t`` also has a similar data
232e66f31c5Sopenharmony_cimember.
233e66f31c5Sopenharmony_ci
234e66f31c5Sopenharmony_ci----
235e66f31c5Sopenharmony_ci
236e66f31c5Sopenharmony_ci.. [#] Depending on the capacity of the hardware of course.
237