在libhv中,除了支持IO事件和定时器事件,还有idle和custom两种事件。idle比较简单,下一篇再分析custom。idle空闲事件,即在空闲时处理的事件
libhv提供了两个接口操作idle事件
//添加idle事件
HV_EXPORT hidle_t* hidle_add(hloop_t* loop, hidle_cb cb, uint32_t repeat DEFAULT(INFINITE));
//删除idle事件
HV_EXPORT void hidle_del(hidle_t* idle);
添加idle事件
hidle_t* hidle_add(hloop_t* loop, hidle_cb cb, uint32_t repeat) {
hidle_t* idle;
HV_ALLOC_SIZEOF(idle); //申请内存
idle->event_type = HEVENT_TYPE_IDLE; //设置事件类型
idle->priority = HEVENT_LOWEST_PRIORITY; //设置优先级
idle->repeat = repeat; //重复次数
list_add(&idle->node, &loop->idles); //添加到空闲链表
EVENT_ADD(loop, idle, cb); //添加事件
loop->nidles++; //空闲事件加1
return idle;
}
空闲事件因为是在没有其他任务时执行的,所以其优先级默认也是最低的,对于空闲事件,管理方式是使用链表,该链表的初始化在hloop_init中调用list_init(&loop->idles)完成的,关于链表可以参考前面的list.h博客。
删除idle事件
static void __hidle_del(hidle_t* idle) {
if (idle->destroy) return;
idle->destroy = 1; //设置销毁标志
list_del(&idle->node); //从链表中删除
idle->loop->nidles--; //空闲事件减1
}
void hidle_del(hidle_t* idle) {
if (!idle->active) return;
EVENT_DEL(idle);
__hidle_del(idle);
}
处理idle事件
int npendings = loop->npendings;
if (npendings == 0) {
if (loop->nidles) {
nidles= hloop_process_idles(loop);
}
}
在hloop_process_events接口中,会先处理定时器事件和IO事件,如果不存在这些事件,而且存在idle事件,那么处理idle事件。
static int hloop_process_idles(hloop_t* loop) {
int nidles = 0;
struct list_node* node = loop->idles.next;
hidle_t* idle = NULL;
while (node != &loop->idles) { //遍历idle列表
idle = IDLE_ENTRY(node);
node = node->next;
if (idle->repeat != INFINITE) {
--idle->repeat; //重复次数减1
}
if (idle->repeat == 0) { //如果不再重复,删除该事件
__hidle_del(idle);
}
EVENT_PENDING(idle); //将idle事件添加到待处理事件集合中
++nidles;
}
return nidles;
}
最终会在hloop_process_pendings接口中,处理添加到待处理事件集合中的事件。
例子
hidle_add(loop, fsync_logfile, INFINITE);
在HttpServer.cpp文件中,使用hidle_add在空闲时间刷新日志缓冲区。