comparison third_party/libuv/docs/src/design.rst @ 160:948de3f54cea

[ThirdParty] Added libuv
author June Park <parkjune1995@gmail.com>
date Wed, 14 Jan 2026 19:39:52 -0800
parents
children
comparison
equal deleted inserted replaced
159:05cf9467a1c3 160:948de3f54cea
1
2 .. _design:
3
4 Design overview
5 ===============
6
7 libuv is cross-platform support library which was originally written for `Node.js`_. It's designed
8 around the event-driven asynchronous I/O model.
9
10 .. _Node.js: https://nodejs.org
11
12 The library provides much more than a simple abstraction over different I/O polling mechanisms:
13 'handles' and 'streams' provide a high level abstraction for sockets and other entities;
14 cross-platform file I/O and threading functionality is also provided, amongst other things.
15
16 Here is a diagram illustrating the different parts that compose libuv and what subsystem they
17 relate to:
18
19 .. image:: static/architecture.png
20 :scale: 75%
21 :align: center
22
23
24 Handles and requests
25 ^^^^^^^^^^^^^^^^^^^^
26
27 libuv provides users with 2 abstractions to work with, in combination with the event loop:
28 handles and requests.
29
30 Handles represent long-lived objects capable of performing certain operations while active. Some examples:
31
32 - A prepare handle gets its callback called once every loop iteration when active.
33 - A TCP server handle that gets its connection callback called every time there is a new connection.
34
35 Requests represent (typically) short-lived operations. These operations can be performed over a
36 handle: write requests are used to write data on a handle; or standalone: getaddrinfo requests
37 don't need a handle they run directly on the loop.
38
39
40 The I/O loop
41 ^^^^^^^^^^^^
42
43 The I/O (or event) loop is the central part of libuv. It establishes the content for all I/O
44 operations, and it's meant to be tied to a single thread. One can run multiple event loops
45 as long as each runs in a different thread. The libuv event loop (or any other API involving
46 the loop or handles, for that matter) **is not thread-safe** except where stated otherwise.
47
48 The event loop follows the rather usual single threaded asynchronous I/O approach: all (network)
49 I/O is performed on non-blocking sockets which are polled using the best mechanism available
50 on the given platform: epoll on Linux, kqueue on OSX and other BSDs, event ports on SunOS and IOCP
51 on Windows. As part of a loop iteration the loop will block waiting for I/O activity on sockets
52 which have been added to the poller and callbacks will be fired indicating socket conditions
53 (readable, writable hangup) so handles can read, write or perform the desired I/O operation.
54
55 In order to better understand how the event loop operates, the following diagram illustrates all
56 stages of a loop iteration:
57
58 .. image:: static/loop_iteration.png
59 :scale: 75%
60 :align: center
61
62
63 #. The loop concept of 'now' is initially set.
64
65 #. Due timers are run if the loop was run with ``UV_RUN_DEFAULT``. All active timers scheduled
66 for a time before the loop's concept of *now* get their callbacks called.
67
68 #. If the loop is *alive* an iteration is started, otherwise the loop will exit immediately. So,
69 when is a loop considered to be *alive*? If a loop has active and ref'd handles, active
70 requests or closing handles it's considered to be *alive*.
71
72 #. Pending callbacks are called. All I/O callbacks are called right after polling for I/O, for the
73 most part. There are cases, however, in which calling such a callback is deferred for the next
74 loop iteration. If the previous iteration deferred any I/O callback it will be run at this point.
75
76 #. Idle handle callbacks are called. Despite the unfortunate name, idle handles are run on every
77 loop iteration, if they are active.
78
79 #. Prepare handle callbacks are called. Prepare handles get their callbacks called right before
80 the loop will block for I/O.
81
82 #. Poll timeout is calculated. Before blocking for I/O the loop calculates for how long it should
83 block. These are the rules when calculating the timeout:
84
85 * If the loop was run with the ``UV_RUN_NOWAIT`` flag, the timeout is 0.
86 * If the loop is going to be stopped (:c:func:`uv_stop` was called), the timeout is 0.
87 * If there are no active handles or requests, the timeout is 0.
88 * If there are any idle handles active, the timeout is 0.
89 * If there are any handles pending to be closed, the timeout is 0.
90 * If none of the above cases matches, the timeout of the closest timer is taken, or
91 if there are no active timers, infinity.
92
93 #. The loop blocks for I/O. At this point the loop will block for I/O for the duration calculated
94 in the previous step. All I/O related handles that were monitoring a given file descriptor
95 for a read or write operation get their callbacks called at this point.
96
97 #. Check handle callbacks are called. Check handles get their callbacks called right after the
98 loop has blocked for I/O. Check handles are essentially the counterpart of prepare handles.
99
100 #. Close callbacks are called. If a handle was closed by calling :c:func:`uv_close` it will
101 get the close callback called.
102
103 #. The loop concept of 'now' is updated.
104
105 #. Due timers are run. Note that 'now' is not updated again until the next loop iteration.
106 So if a timer became due while other timers were being processed, it won't be run until
107 the following event loop iteration.
108
109 #. Iteration ends. If the loop was run with ``UV_RUN_NOWAIT`` or ``UV_RUN_ONCE`` modes the
110 iteration ends and :c:func:`uv_run` will return. If the loop was run with ``UV_RUN_DEFAULT``
111 it will continue from the start if it's still *alive*, otherwise it will also end.
112
113
114 .. important::
115 libuv uses a thread pool to make asynchronous file I/O operations possible, but
116 network I/O is **always** performed in a single thread, each loop's thread.
117
118 .. note::
119 While the polling mechanism is different, libuv makes the execution model consistent
120 across Unix systems and Windows.
121
122
123 File I/O
124 ^^^^^^^^
125
126 Unlike network I/O, there are no platform-specific file I/O primitives libuv could rely on,
127 so the current approach is to run blocking file I/O operations in a thread pool.
128
129 For a thorough explanation of the cross-platform file I/O landscape, check out
130 `this post <https://blog.libtorrent.org/2012/10/asynchronous-disk-io/>`_.
131
132 libuv currently uses a global thread pool on which all loops can queue work. 3 types of
133 operations are currently run on this pool:
134
135 * File system operations
136 * DNS functions (getaddrinfo and getnameinfo)
137 * User specified code via :c:func:`uv_queue_work`
138
139 .. warning::
140 See the :c:ref:`threadpool` section for more details, but keep in mind the thread pool size
141 is quite limited.