blog icon indicating copy to clipboard operation
blog copied to clipboard

libuv源码粗读(2):uv_handle_t 基础句柄结构体介绍

Open xtx1130 opened this issue 6 years ago • 0 comments

本篇文章主要对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 小菜

xtx1130 avatar Aug 29 '18 09:08 xtx1130