UV_RUN_NOWAIT模式如何在libuv中工作?
使用uv_run
函数在libuv中运行事件循环时,会出现一个与以下值一起使用的“mode”参数:
UV_RUN_DEFAULT UV_RUN_ONCE UV_RUN_NOWAIT
前两个是显而易见的。 UV_RUN_DEFAULT
运行事件循环,直到没有更多事件,并且UV_RUN_ONCE
处理来自循环的单个事件。 但是, UV_RUN_NOWAIT
似乎不是一个单独的模式,而是一个可以与其他两个值之一进行OR运算的标志。
默认情况下,此函数会阻塞,直到事件处理UV_RUN_NOWAIT
,并且UV_RUN_NOWAIT
使其无阻塞,但我可以在其上找到的任何文档都在那里结束。 我的问题是,如果你运行事件循环非阻塞,如何处理回调?
libuv事件模型是单线程的(reactor模式),所以我假设它需要阻塞才能调用回调,但如果主线程被占用,事件处理后会发生什么? 在libuv再次控制主线程之前,回调是否会“排队”? 或者是否会在另一个线程上调度回调?
回调以相同的方式处理。 它们将在uv_run()
的线程内运行。
根据文件 :
UV_RUN_DEFAULT
:运行事件循环,直到引用计数降至零。 始终返回零。UV_RUN_ONCE
:轮询一次新事件。 请注意,如果没有挂起事件,此function将阻止。 完成后返回零(没有活动句柄或请求),如果预期有更多事件,则返回非零值(意味着您应该在将来某个时间再次运行事件循环)。UV_RUN_NOWAIT
:轮询新事件一次,但如果没有待处理事件则不阻止。
考虑一个程序有一个监听器监听套接字的情况。 在这种情况下,当套接字已接收数据时将创建一个事件。
- 即使套接字没有数据,
UV_RUN_DEFAULT
也会阻塞调用者。 当以下任何一个时,调用者将从uv_run()
返回:- 循环已通过
uv_stop()
显式停止 - 没有更多的观察者在循环中运行。 例如,唯一的观察者已经停止。
- 循环已通过
- 即使套接字没有数据,
UV_RUN_ONCE
也会阻止调用者。 当出现以下任何一种情况时,调用者将从uv_run()
返回:- 循环已通过
uv_stop()
显式停止 - 没有更多的观察者在循环中运行。 例如,唯一的观察者已经停止。
- 它最多处理了一个事件。 例如,套接字接收数据,并且已调用用户回调。 其他事件可能已准备好处理,但不会在当前的
uv_run()
调用中处理。
- 循环已通过
- 如果套接字没有数据,
UV_RUN_NOWAIT
将返回。
通常,以非阻塞方式运行事件循环以与其他事件循环集成。 考虑一个具有两个事件循环的应用程序:用于后端工作的libuv和用于其自身事件循环的Qt UI(Qt UI)。 能够以非阻塞方式运行事件循环允许单个线程在两个事件循环上分派事件。 这是一个简单的概述,显示了由单个线程处理的两个libuv循环:
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));
如果不使用UV_RUN_NOWAIT
, UV_RUN_NOWAIT
只会在loop1
或loop1
的观察者停止后运行一次。
有关更多信息,请考虑阅读“ libuv简介”中的“ 高级事件循环和进程”部分。