libuv学习笔记(11)
uv_stream_t数据结构以及相关函数
uv_stream_t提供一个抽象的双工通信通道。uv_stream_t是抽象类型,libuv提供3种流测实现:uv_tcp_t,uv_pipe_t以及uv_tty_t
数据结构:
typedef struct uv_stream_s uv_stream_t;
struct uv_stream_s {
UV_HANDLE_FIELDS//uv_handle_t成员,此处不再展开
//UV_STREAM_FIELDS宏展开如下:
#define UV_STREAM_FIELDS
/* number of bytes queued for writing */
size_t write_queue_size;//需要写入的数据量
uv_alloc_cb alloc_cb;//内存分配回调函数
uv_read_cb read_cb;//读取数据回调函数
/* private */
//UV_STREAM_PRIVATE_FIELDS宏展开如下:
unsigned int reqs_pending;
int activecnt;//基于此流的活动请求计数
uv_read_t read_req;//读操作请求
union {
struct
{
unsigned int write_reqs_pending;
uv_shutdown_t* shutdown_req;
} conn;
struct
{
uv_connection_cb connection_cb;
} serv;
} stream;
};
uv_stream_t首先包含uv_handle_t的全部数据,因此uv_stream_t的指针可以转换为uv_handle_t的指针,剩下的数据通过宏UV_STREAM_PRIVATE_FIELDS定义
相关请求类型:
uv_connect_t,连接请求
struct uv_connect_s {
UV_REQ_FIELDS//uv_req_t的数据,此处不再展开
uv_connect_cb cb;//连接回调
uv_stream_t* handle;//
//UV_CONNECT_PRIVATE_FIELDS宏为空
};
uv_shutdown_t,关闭请求
struct uv_shutdown_s {
UV_REQ_FIELDS//uv_req_t的数据,此处不再展开
uv_stream_t* handle;
uv_shutdown_cb cb;//关闭回调
//UV_SHUTDOWN_PRIVATE_FIELDS宏为空
};
uv_write_t,写操作请求
struct uv_write_s {
UV_REQ_FIELDS//uv_req_t的数据,此处不再展开
uv_write_cb cb;//写回调
uv_stream_t* send_handle;//发送对象
uv_stream_t* handle;//
//UV_WRITE_PRIVATE_FIELDS宏展开:
int ipc_header;
uv_buf_t write_buffer;//写内容
HANDLE event_handle;
HANDLE wait_handle;
};
以上三种请求都可以说是uv_req_t的子类,内部都有uv_stream_t对象的指针
相关函数
关闭流的写端。导出函数,在uv.h中声明,steam.c中定义
int uv_shutdown(uv_shutdown_t* req, uv_stream_t* handle, uv_shutdown_cb cb)
{
uv_loop_t* loop = handle->loop;
//stream不可写,返回错误
if (!(handle->flags & UV_HANDLE_WRITABLE)) {
return UV_EPIPE;
}
//初始化请求
uv_req_init(loop, (uv_req_t*) req);
req->type = UV_SHUTDOWN;//类型
req->handle = handle;//与流联系起来
req->cb = cb;/回调函数
handle->flags &= ~UV_HANDLE_WRITABLE;//去掉可写的标记
handle->stream.conn.shutdown_req = req;
handle->reqs_pending++;
//REGISTER_HANDLE_REQ(loop, handle, req);宏展开
do {
//INCREASE_ACTIVE_COUNT((loop), (handle));展开
do {
if ((handle)->activecnt++ == 0) {
uv__handle_start((handle));//第一个请求,开始handle
}
assert((handle)->activecnt > 0);
}
while (0)
//uv__req_register((loop), (req)); 展开:
do {
//将请求添加到loop请求列表的尾端
QUEUE_INSERT_TAIL(&(loop)->active_reqs, &(req)->active_queue);
}
while (0)
}
while (0);
//将流添加到loop的关闭列表
uv_want_endgame(loop, (uv_handle_t*)handle);
return 0;
}
uv_run中调用uv_process_endgames对关闭流的处理:
case UV_TCP:
uv_tcp_endgame(loop, (uv_tcp_t*) handle);
break;
case UV_NAMED_PIPE:
uv_pipe_endgame(loop, (uv_pipe_t*) handle);
break;
case UV_TTY:
uv_tty_endgame(loop, (uv_tty_t*) handle);
break;
之后的学习会对于具体对象的分析
uv_run调用uv_process_reqs对于shutdown请求的处理:
case UV_SHUTDOWN:
//TCP的关闭请求不在此处处理,因为在tcp的关闭处理uv_tcp_endgame中会UNREGISTER_HANDLE_REQ
assert(((uv_shutdown_t*) req)->handle->type == UV_NAMED_PIPE);
uv_process_pipe_shutdown_req(
loop,
(uv_pipe_t*) ((uv_shutdown_t*) req)->handle,
(uv_shutdown_t*) req);
break;
三种请求,对于不同的流对象,会调用不同的实现,具体细节将在之后对应的流对象中分析
转载自原文链接, 如需删除请联系管理员。
原文链接:libuv学习笔记(11),转载请注明来源!