How does UV_RUN_NOWAIT work in libuv?

When starting the event loop in libuv using the uv_run function uv_run there is a "mode" parameter, which is used with the following values:

 UV_RUN_DEFAULT UV_RUN_ONCE UV_RUN_NOWAIT 

The first two are obvious. UV_RUN_DEFAULT starts a cycle of events until there are no more events, and UV_RUN_ONCE process one event from a cycle. However, UV_RUN_NOWAIT not a separate mode, but rather a flag, which can be ORed with one of two other values.

By default, this function is blocked until events are processed, and UV_RUN_NOWAIT makes it non-blocking, but any documentation that I can find on it ends there. My question is: if you run a non-blocking event loop, how are callbacks handled?

The libuv event model is single-threaded (reactor template), so I assume that it must be blocked in order to be able to call callbacks, but if the main thread is busy, what happens to the event after it is processed? Will the callback be queued until libuv takes control of the main thread again? Or will calls be sent to another thread?

+7
source share
1 answer

Callbacks are handled in the same way. They will be executed inside the thread located in uv_run() .

In the documentation:

  • UV_RUN_DEFAULT : starts the event loop until the reference count drops to zero. Always returns zero.
  • UV_RUN_ONCE : poll for new events once. Please note that this function blocks if there are no pending events. Returns zero at completion (without active processing or queries on the left) or nonzero if more events are expected (which means that in the future you should start the event loop again).
  • UV_RUN_NOWAIT : polling new events once, but is not blocked if there are no pending events.

Consider the case when a program has one observer listening to a socket. In this case, an event will be raised when the socket receives data.

  • UV_RUN_DEFAULT block the caller, even if the socket has no data. The caller will return with uv_run() if:
    • The loop was explicitly stopped via uv_stop()
    • There are no more observers in the loop. For example, a single observer is stopped.
  • UV_RUN_ONCE blocks the caller, even if the socket has no data. The caller will return with uv_run() when one of the following events occurs:
    • The loop was explicitly stopped via uv_stop()
    • There are no more observers in the loop. For example, a single observer is stopped.
    • He handled a maximum of one event. For example, a socket received data, and a user callback was called. Additional events may be ready to be processed, but will not be processed in the current uv_run() call.
  • UV_RUN_NOWAIT will return if there is no data in the socket.

Often the start time of an event loop in non-blocking mode is performed to integrate with other event loops. Consider an application with two event loops: libuv for working with the backend and Qt UI (which is controlled by its own event loop). The ability to start the event loop in non-blocking mode allows one thread to send events on both event loops. Here is a simplified overview showing that two libuv loops are processed by a single thread:

 uv_loop_t *loop1 = uv_loop_new(); uv_loop_t *loop2 = uv_loop_new(); // create, initialize, and start a watcher for each loop. ... // Handle two event loops with a single thread. while (uv_run(loop1, UV_RUN_NOWAIT) || uv_run(loop2, UV_RUN_NOWAIT)); 

Without using UV_RUN_NOWAIT , loop2 will only be executed once. loop1 or loop1 watchers were stopped.

For more information, see the Advanced Event Loops section and the Processes sections of Introduction to libuv .

+9
source

All Articles