【问题标题】:How does the UV_RUN_NOWAIT mode work in libuv?UV_RUN_NOWAIT 模式在 libuv 中是如何工作的?
【发布时间】:2013-06-10 15:41:51
【问题描述】:

当使用 uv_run 函数在 libuv 中运行事件循环时,有一个“mode”参数与以下值一起使用:

UV_RUN_DEFAULT
UV_RUN_ONCE
UV_RUN_NOWAIT

前两个很明显。 UV_RUN_DEFAULT 运行事件循环,直到没有更多事件,UV_RUN_ONCE 处理循环中的单个事件。但是,UV_RUN_NOWAIT 似乎不是一个单独的模式,而是一个可以与其他两个值之一进行或运算的标志。

默认情况下,这个函数会阻塞直到事件处理完毕,UV_RUN_NOWAIT 使它成为非阻塞的,但我能找到的任何文档都到此为止。我的问题是,如果你非阻塞地运行事件循环,回调是如何处理的?

libuv 事件模型是单线程的(反应器模式),所以我假设它需要阻塞才能调用回调,但是如果主线程被占用,事件处理后会发生什么?回调是否会被“排队”直到 libuv 再次控制主线程?还是会在另一个线程上分派回调?

【问题讨论】:

    标签: c nonblocking libuv evented-io


    【解决方案1】:

    回调以相同的方式处理。它们将在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() 明确停止
      • 没有更多的观察者在循环中运行。例如,唯一的观察者已停止。
      • 它最多处理了一个事件。比如socket接收到数据,调用了用户回调。其他事件可能已准备好处理,但不会在当前的uv_run() 调用中处理。
    • 如果套接字没有数据,UV_RUN_NOWAIT 将返回。

    通常,以非阻塞方式运行事件循环是为了与其他事件循环集成。考虑一个有两个事件循环的应用程序:用于后端工作的 libuv 和 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 的观察者停止后运行。

    有关更多信息,请考虑阅读An Introduction to libuvAdvanced Event LoopsProcesses 部分。

    【讨论】:

    猜你喜欢
    • 2020-07-24
    • 1970-01-01
    • 2011-05-06
    • 1970-01-01
    • 2013-02-12
    • 2019-01-07
    • 2017-06-19
    • 2011-02-23
    • 2015-12-18
    相关资源
    最近更新 更多