7.先进的事件循环
Libuv提供了对事件循环的大量用户控制,您可以通过同时处理多个循环来获得有趣的结果。你也可以将libuv的事件循环嵌入到另一个基于事件循环的库中——想象一个基于Qt的UI, Qt的事件循环驱动一个libuv后台,执行密集的系统级任务。
停止事件循环
Uv_stop()可以用来停止一个事件循环。循环在下一次迭代中停止运行的时间最早,可能更晚。这意味着在此循环迭代中准备处理的事件仍将被处理,因此uv_stop()不能用作终止开关。当uv_stop()被调用时,循环不会阻塞这个迭代的i/o。这些东西的语义可能有点难以理解,所以让我们看看所有控制流发生的uv_run()。
src/unix/core.c - uv_run
1 QUEUE_REMOVE(&handle->handle_queue); 2 3 if (handle->close_cb) { 4 handle->close_cb(handle); 5 } 6 } 7 8 9 static void uv__run_closing_handles(uv_loop_t* loop) { 10 uv_handle_t* p; 11 uv_handle_t* q; 12 13 p = loop->closing_handles; 14 loop->closing_handles = NULL; 15 16 while (p) { 17 q = p->next_closing; 18 uv__finish_close(p); 19 p = q; 20 } 21 }
Stop_flag由uv_stop()设置。现在所有的libuv回调函数都在事件循环中被调用,这就是为什么在它们中调用uv_stop()仍然会导致这个循环的迭代发生。首先,libuv更新计时器,然后运行挂起计时器、空闲和准备回调,并调用任何挂起的I/O回调。如果你要在其中任何一个调用uv_stop(), stop_flag都会被设置。这会导致uv_backend_timeout()返回0,这就是为什么循环不会在I/O上阻塞。另一方面,如果您在一个检查处理程序中调用了uv_stop(),那么I/O已经完成,不受影响。
Uv_stop()用于在计算结果或出现错误时关闭循环,而不必确保所有处理程序都被逐个停止。
下面是一个停止循环的简单示例,并演示了循环的当前迭代是如何继续进行的。
uvstop/main.c
1 #include <stdio.h> 2 #include <uv.h> 3 4 int64_t counter = 0; 5 6 void idle_cb(uv_idle_t *handle) { 7 printf("Idle callback\n"); 8 counter++; 9 10 if (counter >= 5) { 11 uv_stop(uv_default_loop()); 12 printf("uv_stop() called\n"); 13 } 14 } 15 16 void prep_cb(uv_prepare_t *handle) { 17 printf("Prep callback\n"); 18 } 19 20 int main() { 21 uv_idle_t idler; 22 uv_prepare_t prep; 23 24 uv_idle_init(uv_default_loop(), &idler); 25 uv_idle_start(&idler, idle_cb); 26 27 uv_prepare_init(uv_default_loop(), &prep); 28 uv_prepare_start(&prep, prep_cb); 29 30 uv_run(uv_default_loop(), UV_RUN_DEFAULT); 31 32 return 0; 33 }

浙公网安备 33010602011771号