Mercurial
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. |