blog
blog copied to clipboard
libuv源码粗读(2):uv_handle_t 基础句柄结构体介绍
本篇文章主要对
uv_handle_t
结构体进行展开介绍
uv_handle_t声明
直接从uv.h切入,很容易便能找到uv_handle_t
结构体的声明:
typedef struct uv_handle_s uv_handle_t;
uv_handle_s的定义
在uv_handle_s
的定义中有如下注释:
/* The abstract base class of all handles. */
/* 所有句柄的抽象基类 */
struct uv_handle_s {
UV_HANDLE_FIELDS
};
意即uv_##name##_t
全部继承自uv_handle_t
,让我们详细展开UV_HANDLE_FIELDS
一窥究竟:
#define UV_HANDLE_FIELDS \
/* public */ \
void* data; \
/* read-only */ \
uv_loop_t* loop; \
uv_handle_type type; \
/* private */ \
uv_close_cb close_cb; \
void* handle_queue[2]; \
union { \
int fd; \
void* reserved[4]; \
} u; \
UV_HANDLE_PRIVATE_FIELDS \
简单对内部的数据结构做下介绍:
- loop 为句柄所属的事件循环
- type 为句柄类型,和
uv_##name##_t
强相关,对应的uv_##name##_t
的type为UV_##NAME##
。这种情况下可以通过handle->type
很容易判断出来uv_handle_t
子类的类型。 - close_cb 句柄关闭时候执行的回调,入参参数为
uv_handle_t
的指针 - handle_queue 句柄队列指针
- u.fd 文件描述符
UV_HANDLE_PRIVATE_FIELDS
展开代码如下(unix):
#define UV_HANDLE_PRIVATE_FIELDS \
uv_handle_t* next_closing; \
unsigned int flags; \
- next_closing 下一个需要关闭的句柄,可以使得
loop->closing_handles
形成一个链表结构,从而方便删除:
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;
}
在初始化时,会把handle->next_closing
以及loop->closing_handles
全部置空。通过这段代码,可以清晰的看到在关闭句柄的时候,只需要判断handle->next_closing
是否为null就可以得知所有句柄是否已经全部关闭。
- flags 是对handle状态的标记。
继承的实现
在这里我们以uv_poll_s
结构体为例,来解读一下libuv如何使用宏实现的类似继承的操作:
struct uv_poll_s {
UV_HANDLE_FIELDS
uv_poll_cb poll_cb;
UV_POLL_PRIVATE_FIELDS
};
在uv_poll_s
数据结构中,第一个使用的宏便是UV_HANDLE_FIELDS
宏,其次才为uv_poll_s
的私有宏。所有的uv_##name##_t
均包含了uv_handle_t
的结构体变量,所以任何的uv_##name##_t
都可以转换为uv_handle_t
。
至此,整个uv_handle_t
就介绍完了。
by 小菜