Libuv check句柄
结合libuv的事件循环过程,在每个循环周期会执行 uv__run_check ()函数 ,如下图:

Demo
#include <stdio.h>
#include <stdlib.h>
#include <uv.h>
int64_t num = 0;
void idle_cb(uv_idle_t* handle)
{
num++;
printf("idle callback\n");
if (num >= 5) {
printf("idle stop, num = %ld\n", num);
uv_stop(uv_default_loop());
}
}
void check_cb(uv_check_t *handle)
{
printf("check callback\n");
}
int main()
{
uv_idle_t idler;
uv_check_t check;
uv_idle_init(uv_default_loop(), &idler);
uv_idle_start(&idler, idle_cb);
uv_check_init(uv_default_loop(), &check);
uv_check_start(&check, check_cb);
uv_run(uv_default_loop(), UV_RUN_DEFAULT);
return 0;
}
执行结果:
idle callback
check callback
idle callback
check callback
idle callback
check callback
idle callback
check callback
idle callback
idle stop, num = 5
check callback
空闲句柄的API函数
初始化句柄
int uv_check_init(uv_loop_t* loop, uv_check_t* check)
设置回调函数
int uv_check_start(uv_check_t* check, uv_check_cb cb)
停止
int uv_check_stop(uv_check_t* check)
同uv_idle_init这个函数的话,是找不到它的具体源码如下:
src\unix\loop-watcher.c文件内容
#include "uv.h"
#include "internal.h"
#define UV_LOOP_WATCHER_DEFINE(name, type) \
int uv_##name##_init(uv_loop_t* loop, uv_##name##_t* handle) { \
uv__handle_init(loop, (uv_handle_t*)handle, UV_##type); \
handle->name##_cb = NULL; \
return 0; \
} \
\
int uv_##name##_start(uv_##name##_t* handle, uv_##name##_cb cb) { \
if (uv__is_active(handle)) return 0; \
if (cb == NULL) return UV_EINVAL; \
QUEUE_INSERT_HEAD(&handle->loop->name##_handles, &handle->queue); \
handle->name##_cb = cb; \
uv__handle_start(handle); \
return 0; \
} \
\
int uv_##name##_stop(uv_##name##_t* handle) { \
if (!uv__is_active(handle)) return 0; \
QUEUE_REMOVE(&handle->queue); \
uv__handle_stop(handle); \
return 0; \
} \
\
void uv__run_##name(uv_loop_t* loop) { \
uv_##name##_t* h; \
QUEUE queue; \
QUEUE* q; \
QUEUE_MOVE(&loop->name##_handles, &queue); \
while (!QUEUE_EMPTY(&queue)) { \
q = QUEUE_HEAD(&queue); \
h = QUEUE_DATA(q, uv_##name##_t, queue); \
QUEUE_REMOVE(q); \
QUEUE_INSERT_TAIL(&loop->name##_handles, q); \
h->name##_cb(h); \
} \
} \
\
void uv__##name##_close(uv_##name##_t* handle) { \
uv_##name##_stop(handle); \
}
UV_LOOP_WATCHER_DEFINE(prepare, PREPARE)
UV_LOOP_WATCHER_DEFINE(check, CHECK)
UV_LOOP_WATCHER_DEFINE(idle, IDLE)
针对check handle 宏定义展开后如下:
int uv_check_init(uv_loop_t* loop, uv_check_t* handle) {
/* 初始化handle的类型,所属loop,设置UV_HANDLE_REF标志,并且把handle插入loop->handle_queue队列的队尾 */
uv__handle_init(loop, (uv_handle_t*)handle, UV_IDLE);
handle->check_cb = NULL;
return 0;
}
int uv_check_start(uv_check_t* handle, uv_check_cb cb) {
/* 如果已经执行过start函数则直接返回 */
if (uv__is_active(handle)) return 0;
/* 回调函数不允许为空 */
if (cb == NULL) return UV_EINVAL;
/* 把handle插入loop中check_handles队列,loop有prepare,check和check三个队列 */
QUEUE_INSERT_HEAD(&handle->loop->check_handles, &handle->queue);
/* 指定回调函数,在事件循环迭代的时候被执行 */
handle->check_cb = cb;
/* 启动check handle,设置UV_HANDLE_ACTIVE标记并且将loop中的handle的active计数加一,
init的时候只是把handle挂载到loop,start的时候handle才处于激活态 */
uv__handle_start(handle);
return 0;
}
int uv_check_stop(uv_check_t* handle) {
/* 如果check handle没有被启动则直接返回 */
if (!uv__is_active(handle)) return 0;
/* 把handle从loop中相应的队列移除,但是还挂载到handle_queue中 */
QUEUE_REMOVE(&handle->queue);
/* 清除UV_HANDLE_ACTIVE标记并且减去loop中handle的active计数 */
uv__handle_stop(handle);
return 0;
}
/* 在每一轮循环中执行该函数,具体见uv_run */
void uv__run_check(uv_loop_t* loop) {
uv_check_t* h;
QUEUE queue;
QUEUE* q;
/* 把loop的check_handles队列中所有节点摘下来挂载到queue变量 */
QUEUE_MOVE(&loop->check_handles, &queue);
/* while循环遍历队列,执行每个节点里面的函数 */
while (!QUEUE_EMPTY(&queue)) {
/* 取下当前待处理的节点 */
q = QUEUE_HEAD(&queue);
/* 取得该节点对应的整个结构体的基地址 */
h = QUEUE_DATA(q, uv_check_t, queue);
/* 把该节点移出当前队列 */
QUEUE_REMOVE(q);
/* 重新插入loop->check_handles队列 */
QUEUE_INSERT_TAIL(&loop->check_handles, q);
/* 执行对应的回调函数 */
h->check_cb(h);
}
}
/* 关闭这个check handle */
void uv__check_close(uv_check_t* handle) {
uv_check_stop(handle);
}