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 }

 

posted @ 2021-05-11 20:17  风吹大风车  阅读(149)  评论(0)    收藏  举报