comparison third_party/libuv/docs/src/migration_010_100.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 .. _migration_010_100:
3
4 libuv 0.10 -> 1.0.0 migration guide
5 ===================================
6
7 Some APIs changed quite a bit throughout the 1.0.0 development process. Here
8 is a migration guide for the most significant changes that happened after 0.10
9 was released.
10
11
12 Loop initialization and closing
13 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
14
15 In libuv 0.10 (and previous versions), loops were created with `uv_loop_new`, which
16 allocated memory for a new loop and initialized it; and destroyed with `uv_loop_delete`,
17 which destroyed the loop and freed the memory. Starting with 1.0, those are deprecated
18 and the user is responsible for allocating the memory and then initializing the loop.
19
20 libuv 0.10
21
22 ::
23
24 uv_loop_t* loop = uv_loop_new();
25 ...
26 uv_loop_delete(loop);
27
28 libuv 1.0
29
30 ::
31
32 uv_loop_t* loop = malloc(sizeof *loop);
33 uv_loop_init(loop);
34 ...
35 uv_loop_close(loop);
36 free(loop);
37
38 .. note::
39 Error handling was omitted for brevity. Check the documentation for :c:func:`uv_loop_init`
40 and :c:func:`uv_loop_close`.
41
42
43 Error handling
44 ~~~~~~~~~~~~~~
45
46 Error handling had a major overhaul in libuv 1.0. In general, functions and status parameters
47 would get 0 for success and -1 for failure on libuv 0.10, and the user had to use `uv_last_error`
48 to fetch the error code, which was a positive number.
49
50 In 1.0, functions and status parameters contain the actual error code, which is 0 for success, or
51 a negative number in case of error.
52
53 libuv 0.10
54
55 ::
56
57 ... assume 'server' is a TCP server which is already listening
58 r = uv_listen((uv_stream_t*) server, 511, NULL);
59 if (r == -1) {
60 uv_err_t err = uv_last_error(uv_default_loop());
61 /* err.code contains UV_EADDRINUSE */
62 }
63
64 libuv 1.0
65
66 ::
67
68 ... assume 'server' is a TCP server which is already listening
69 r = uv_listen((uv_stream_t*) server, 511, NULL);
70 if (r < 0) {
71 /* r contains UV_EADDRINUSE */
72 }
73
74
75 Threadpool changes
76 ~~~~~~~~~~~~~~~~~~
77
78 In libuv 0.10 Unix used a threadpool which defaulted to 4 threads, while Windows used the
79 `QueueUserWorkItem` API, which uses a Windows internal threadpool, which defaults to 512
80 threads per process.
81
82 In 1.0, we unified both implementations, so Windows now uses the same implementation Unix
83 does. The threadpool size can be set by exporting the ``UV_THREADPOOL_SIZE`` environment
84 variable. See :c:ref:`threadpool`.
85
86
87 Allocation callback API change
88 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
89
90 In libuv 0.10 the callback had to return a filled :c:type:`uv_buf_t` by value:
91
92 ::
93
94 uv_buf_t alloc_cb(uv_handle_t* handle, size_t size) {
95 return uv_buf_init(malloc(size), size);
96 }
97
98 In libuv 1.0 a pointer to a buffer is passed to the callback, which the user
99 needs to fill:
100
101 ::
102
103 void alloc_cb(uv_handle_t* handle, size_t size, uv_buf_t* buf) {
104 buf->base = malloc(size);
105 buf->len = size;
106 }
107
108
109 Unification of IPv4 / IPv6 APIs
110 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
111
112 libuv 1.0 unified the IPv4 and IPv6 APIS. There is no longer a `uv_tcp_bind` and `uv_tcp_bind6`
113 duality, there is only :c:func:`uv_tcp_bind` now.
114
115 IPv4 functions took ``struct sockaddr_in`` structures by value, and IPv6 functions took
116 ``struct sockaddr_in6``. Now functions take a ``struct sockaddr*`` (note it's a pointer).
117 It can be stack allocated.
118
119 libuv 0.10
120
121 ::
122
123 struct sockaddr_in addr = uv_ip4_addr("0.0.0.0", 1234);
124 ...
125 uv_tcp_bind(&server, addr)
126
127 libuv 1.0
128
129 ::
130
131 struct sockaddr_in addr;
132 uv_ip4_addr("0.0.0.0", 1234, &addr)
133 ...
134 uv_tcp_bind(&server, (const struct sockaddr*) &addr, 0);
135
136 The IPv4 and IPv6 struct creating functions (:c:func:`uv_ip4_addr` and :c:func:`uv_ip6_addr`)
137 have also changed, make sure you check the documentation.
138
139 ..note::
140 This change applies to all functions that made a distinction between IPv4 and IPv6
141 addresses.
142
143
144 Streams / UDP data receive callback API change
145 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
146
147 The streams and UDP data receive callbacks now get a pointer to a :c:type:`uv_buf_t` buffer,
148 not a structure by value.
149
150 libuv 0.10
151
152 ::
153
154 void on_read(uv_stream_t* handle,
155 ssize_t nread,
156 uv_buf_t buf) {
157 ...
158 }
159
160 void recv_cb(uv_udp_t* handle,
161 ssize_t nread,
162 uv_buf_t buf,
163 struct sockaddr* addr,
164 unsigned flags) {
165 ...
166 }
167
168 libuv 1.0
169
170 ::
171
172 void on_read(uv_stream_t* handle,
173 ssize_t nread,
174 const uv_buf_t* buf) {
175 ...
176 }
177
178 void recv_cb(uv_udp_t* handle,
179 ssize_t nread,
180 const uv_buf_t* buf,
181 const struct sockaddr* addr,
182 unsigned flags) {
183 ...
184 }
185
186
187 Receiving handles over pipes API change
188 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
189
190 In libuv 0.10 (and earlier versions) the `uv_read2_start` function was used to start reading
191 data on a pipe, which could also result in the reception of handles over it. The callback
192 for such function looked like this:
193
194 ::
195
196 void on_read(uv_pipe_t* pipe,
197 ssize_t nread,
198 uv_buf_t buf,
199 uv_handle_type pending) {
200 ...
201 }
202
203 In libuv 1.0, `uv_read2_start` was removed, and the user needs to check if there are pending
204 handles using :c:func:`uv_pipe_pending_count` and :c:func:`uv_pipe_pending_type` while in
205 the read callback:
206
207 ::
208
209 void on_read(uv_stream_t* handle,
210 ssize_t nread,
211 const uv_buf_t* buf) {
212 ...
213 while (uv_pipe_pending_count((uv_pipe_t*) handle) != 0) {
214 pending = uv_pipe_pending_type((uv_pipe_t*) handle);
215 ...
216 }
217 ...
218 }
219
220
221 Extracting the file descriptor out of a handle
222 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
223
224 While it wasn't supported by the API, users often accessed the libuv internals in
225 order to get access to the file descriptor of a TCP handle, for example.
226
227 ::
228
229 fd = handle->io_watcher.fd;
230
231 This is now properly exposed through the :c:func:`uv_fileno` function.
232
233
234 uv_fs_readdir rename and API change
235 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
236
237 `uv_fs_readdir` returned a list of strings in the `req->ptr` field upon completion in
238 libuv 0.10. In 1.0, this function got renamed to :c:func:`uv_fs_scandir`, since it's
239 actually implemented using ``scandir(3)``.
240
241 In addition, instead of allocating a full list strings, the user is able to get one
242 result at a time by using the :c:func:`uv_fs_scandir_next` function. This function
243 does not need to make a roundtrip to the threadpool, because libuv will keep the
244 list of *dents* returned by ``scandir(3)`` around.