上一篇说了一下整体的事件循环,对于UV_RUN_DEFAULT模式来调用uv_run来说,uv__loop_alive就决定了是否退出,这一篇看一下uv__loop_alive的源码。
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
uv__has_active_handles就是检查loop->active_handles值是否大于0.
#define uv__has_active_handles(loop) \
((loop)->active_handles > 0)
/* Handle types. */
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不在其中,可能与其调用方式有关,我暂时无法解释
#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++
#define uv__active_handle_add(h) \
do { \
(h)->loop->active_handles++; \
} \
while (0)
相应的在handle结束时有uv__active_handle_rm的调用,(h)->loop->active_handles减一。
#define uv__active_handle_rm(h) \
do { \
(h)->loop->active_handles--; \
} \
while (0)
uv__has_active_reqs和handle的道理一样,是检测(loop)->active_reqs.count > 0。active_reqs是个共用体,它的另一个用途暂时我还不知道。
#define uv__has_active_reqs(loop) \
((loop)->active_reqs.count > 0)
/* Request types. */
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。
#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。
#define uv__req_unregister(loop, req) \
do { \
assert(uv__has_active_reqs(loop)); \
(loop)->active_reqs.count--; \
} \
while (0)
要关闭的handle会以链表的形式挂在loop->closing_handles上。这个操作通过调用uv__make_close_pending来实现。
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的回调函数。