UV_RUN_NOWAIT模式如何在libuv中工作?

时间:2013-06-14 04:01:05

标签: c nonblocking libuv evented-io

使用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使其无阻塞,但我可以在其上找到的任何文档都在那里结束。我的问题是,如果你运行事件循环非阻塞,如何处理回调?

libuv事件模型是单线程的(reactor模式),所以我假设它需要阻塞才能调用回调,但是如果主线程被占用,那么事件处理后会发生什么?在libuv再次控制主线程之前,回调是否会“排队”?或者是否会在另一个线程上调度回调?

1 个答案:

答案 0 :(得分:10)

回调以相同的方式处理。它们将在uv_run()

中的线程内运行

根据documentation

  
      
  • UV_RUN_DEFAULT:运行事件循环,直到引用计数降为零。始终返回零。
  •   
  • UV_RUN_ONCE:轮询新活动一次。请注意,如果没有挂起事件,此功能将阻止。完成后返回零(没有活动句柄或请求),如果预期会有更多事件,则返回非零值(意味着您应该在将来的某个时间再次运行事件循环)。
  •   
  • 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_NOWAITloop2只会在loop1loop1的观察者停止后才会投放。

有关详细信息,请考虑阅读Advanced Event LoopsProcessesAn Introduction to libuv部分。