idle事件

赵飞雨
2023-12-01

在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在空闲时间刷新日志缓冲区。

 

 类似资料: