前言
上一篇说了一下整体的事件循环,对于UV_RUN_DEFAULT模式来调用uv_run来说,uv__loop_alive就决定了是否退出,这一篇看一下uv__loop_alive的源码。
详情
1 2 3 4 5
| static int uv__loop_alive(const uv_loop_t* loop) { return uv__has_active_handles(loop) || uv__has_active_reqs(loop) || loop->closing_handles != NULL; }
|
可见loop的状态取决于三个方面:handles、reqs、closing_handles
handles
uv__has_active_handles就是检查loop->active_handles值是否大于0.
1 2
| #define uv__has_active_handles(loop) \ ((loop)->active_handles > 0)
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| typedef struct uv_loop_s uv_loop_t; typedef struct uv_handle_s uv_handle_t; typedef struct uv_dir_s uv_dir_t; typedef struct uv_stream_s uv_stream_t; typedef struct uv_tcp_s uv_tcp_t; typedef struct uv_udp_s uv_udp_t; typedef struct uv_pipe_s uv_pipe_t; typedef struct uv_tty_s uv_tty_t; typedef struct uv_poll_s uv_poll_t; typedef struct uv_timer_s uv_timer_t; typedef struct uv_prepare_s uv_prepare_t; typedef struct uv_check_s uv_check_t; typedef struct uv_idle_s uv_idle_t; typedef struct uv_async_s uv_async_t; typedef struct uv_process_s uv_process_t; typedef struct uv_fs_event_s uv_fs_event_t; typedef struct uv_fs_poll_s uv_fs_poll_t; typedef struct uv_signal_s uv_signal_t;
|
handles列表如上。handle在调用时,会包含一个函数的调用,就是
uv__handle_start。下图所示,是哪些函数调用了uv__handle_start。有一些handle不在其中,可能与其调用方式有关,我暂时无法解释
1 2 3 4 5 6 7
| #define uv__handle_start(h) \ do { \ if (((h)->flags & UV_HANDLE_ACTIVE) != 0) break; \ (h)->flags |= UV_HANDLE_ACTIVE; \ if (((h)->flags & UV_HANDLE_REF) != 0) uv__active_handle_add(h); \ } \ while (0)
|
uv__handle_start函数在调用时,会调用uv__active_handle_add,uv__active_handle_add就是将loop->active_handles++
1 2 3 4 5
| #define uv__active_handle_add(h) \ do { \ (h)->loop->active_handles++; \ } \ while (0)
|
相应的在handle结束时有uv__active_handle_rm的调用,(h)->loop->active_handles减一。
1 2 3 4 5
| #define uv__active_handle_rm(h) \ do { \ (h)->loop->active_handles--; \ } \ while (0)
|
req
uv__has_active_reqs和handle的道理一样,是检测(loop)->active_reqs.count > 0。active_reqs是个共用体,它的另一个用途暂时我还不知道。
1 2
| #define uv__has_active_reqs(loop) \ ((loop)->active_reqs.count > 0)
|
1 2 3 4 5 6 7 8 9 10
| typedef struct uv_req_s uv_req_t; typedef struct uv_getaddrinfo_s uv_getaddrinfo_t; typedef struct uv_getnameinfo_s uv_getnameinfo_t; typedef struct uv_shutdown_s uv_shutdown_t; typedef struct uv_write_s uv_write_t; typedef struct uv_connect_s uv_connect_t; typedef struct uv_udp_send_s uv_udp_send_t; typedef struct uv_fs_s uv_fs_t; typedef struct uv_work_s uv_work_t;
|
uv__req_register(loop, req)等同于handle的uv__active_handle_add。uv__req_register在uv__req_init中调用,几乎(漏网的暂时没法解释 )每个req在初始化时都调用了uv__req_init。
1 2 3 4 5 6 7 8 9 10 11 12
| #define uv__req_init(loop, req, typ) \ do { \ UV_REQ_INIT(req, typ); \ uv__req_register(loop, req); \ } \ while (0) #define uv__req_register(loop, req) \ do { \ (loop)->active_reqs.count++; \ } \ while (0)
|
下图所示是那些函数调用了uv__req_init,由名称我们可以看出来它们是属于哪些req的。
同理,还有uv__req_unregister。
1 2 3 4 5 6
| #define uv__req_unregister(loop, req) \ do { \ assert(uv__has_active_reqs(loop)); \ (loop)->active_reqs.count--; \ } \ while (0)
|
closing_handles
要关闭的handle会以链表的形式挂在loop->closing_handles上。这个操作通过调用uv__make_close_pending来实现。
1 2 3 4 5 6
| void uv__make_close_pending(uv_handle_t* handle) { assert(handle->flags & UV_HANDLE_CLOSING); assert(!(handle->flags & UV_HANDLE_CLOSED)); handle->next_closing = handle->loop->closing_handles; handle->loop->closing_handles = handle; }
|
如果closing_handles不为空,那么还需要进入事件循环,去调用关闭的handle的回调函数。