Libuv:Design
lastmod 2018-08-17created 2016-01-169 edits
libuv is a cross-platform library written for Node.js. It is designed around an event-driven asynchronous I/O model. It provides a simple abstraction on top of various I/O polling mechanisms.
Handles and requests
libuv is provided as a combination of an event loop and two abstraction objects.
- Handle
- Request
The I/O loop
libuv Loop iteration The I/O Loop (or Event loop) is the central part of libuv. It sets up the context for all I/O operations and is meant to be tied to a single thread.
| Warning |
| Multiple event loops each run in a different thread, and the event loop is not thread-safe unless stated otherwise. 1 |
The event loop uses the usual single-threaded asynchronous I/O approach. Polling of all (network) I/O non-blocking sockets uses the best mechanism available on the given platform.
- epoll on Linux
- kqueue on OSX and other BSDs
- event ports on SunOS
- IOCP on Windows.
The loop proceeds in the following order.
- An update takes place. The current time is cached to reduce the number of system calls.
- If the LOOP is not alive, it exits immediately. The LOOP is alive if a reference handle is active, a request is active, or a handle is closing (closing handle). 2
- Due timers are run.
- Pending callbacks are called. All I/O callbacks are called after I/O polling. If deferral to the next loop is needed, it runs at this point. If the previous iteration was deferred, all I/O callbacks are called at this point.
- Idle handle callbacks are called.
- Prepare handle callbacks are called.
- The poll timeout is calculated. The rules for calculating the timeout are as follows:
- If the loop was run with the
UV_RUN_NOWAITflag, the timeout is 0. - If the loop is going to be stopped (
uv_stop()was called), the timeout is 0. - If there are no active handles or requests, the timeout is 0.
- If there are any idle handles active, the timeout is 0.
- If there are any handles pending to be closed, the timeout is 0.
- If none of the above cases was matched, the timeout of the closest timer is taken, or if there are no active timers, infinity.
- If the loop was run with the
- The loop blocks for I/O.
- Check handle callbacks are called.
- Close callbacks are called.
- Special case in case the loop was run with
UV_RUN_ONCE, as it implies forward progress. - Iteration ends.
| Important |
| libuv uses a thread pool to make asynchronous file I/O operations possible, but network I/O always runs on a single thread. |