libuv学习笔记(4)
uv_req_t 基本请求的定义以及相关函数
结构体定义
与uv_handlt_t结构体类似,将通用的数据结构定义为UV_REQ_FIELDS宏,每种类型的请求都在相同位置(开始)包含该宏,所以任何req类型的指针都能转换为uv_req_t*,实现了类似继承的效果。
typedef struct uv_req_s uv_req_t;
struct uv_req_s
{
//UV_REQ_FIELDS宏展开:
/* 指向用户自定义数据 */
void* data;
/* 请求类型,只读 */
uv_req_type type;
/* 私有数据 */
void* active_queue[2];
void* reserved[4];
//UV_REQ_PRIVATE_FIELDS 宏展开(在uv-win.h中定义,平台相关) :
union {
/* i/o操作,iocp用到 */
struct {
OVERLAPPED overlapped;
size_t queued_bytes;
} io;
} u;
struct uv_req_s* next_req;//指向下一个请求
};
请求类型包括(宏展开后):
typedef enum {
UV_UNKNOWN_REQ = 0,
UV_REQ,
UV_CONNECT,//连接
UV_WRITE,//写
UV_SHUTDOWN,//关闭
UV_UDP_SEND,//发送udp数据
UV_FS,//文件操作
UV_WORK,//在线程池中运行
UV_GETADDRINFO,//获取地址
UV_GETNAMEINFO,//获取主机名
//内部请求类型
UV_ACCPTE,//接受连接
UV_FS_EVENT_REQ, //文件事件
UV_POLL_REQ, //轮询
UV_PROCESS_EXIT, //关闭进程
UV_READ,//读取
UV_UDP_RECV, //udp socket接收数据
UV_WAKEUP, //
UV_SIGNAL_REQ,//信号
UV_REQ_TYPE_MAX
} uv_req_type;
相关函数
1.取消请求,导出函数,uv.h中声明,threadpool.c中定义
int uv_cancel(uv_req_t* req)
{
struct uv__work* wreq;
uv_loop_t* loop;
//根据请求类型获取对应的请求指针,只支持取消通过线程池处理的请求(4类)
switch (req->type) {
case UV_FS:
loop = ((uv_fs_t*) req)->loop;
wreq = &((uv_fs_t*) req)->work_req;
break;
case UV_GETADDRINFO:
loop = ((uv_getaddrinfo_t*) req)->loop;
wreq = &((uv_getaddrinfo_t*) req)->work_req;
break;
case UV_GETNAMEINFO:
loop = ((uv_getnameinfo_t*) req)->loop;
wreq = &((uv_getnameinfo_t*) req)->work_req;
break;
case UV_WORK:
loop = ((uv_work_t*) req)->loop;
wreq = &((uv_work_t*) req)->work_req;
break;
default:
return UV_EINVAL;
}
//调用内部函数
return uv__work_cancel(loop, req, wreq);
}
内部函数 uv__work_cancel
static int uv__work_cancel(uv_loop_t* loop, uv_req_t* req, struct uv__work* w)
{
int cancelled;
//互斥量锁定(内部通过临界区实现),然后移除请求对象(req)的工作项(w)
uv_mutex_lock(&mutex);
uv_mutex_lock(&w->loop->wq_mutex);
cancelled = !QUEUE_EMPTY(&w->wq) && w->work != NULL;
if (cancelled)
QUEUE_REMOVE(&w->wq);
uv_mutex_unlock(&w->loop->wq_mutex);
uv_mutex_unlock(&mutex);
if (!cancelled)
return UV_EBUSY;
//工作函数设为uv__cancelled,后面loop会根据这个值判断请求是否是取消的(uv__work_done)
w->work = uv__cancelled;
uv_mutex_lock(&loop->wq_mutex);
//将请求添加到loop的完成请求的列表
QUEUE_INSERT_TAIL(&loop->wq, &w->wq);
//发送异步消息,wakeup loop
uv_async_send(&loop->wq_async);
uv_mutex_unlock(&loop->wq_mutex);
return 0;
}
不同类型的请求会有不同的API,将会在之后具体分析。