int
event_base_loop(struct event_base *base, int flags)
{
const struct eventop *evsel = base->evsel;//选择了epoll机制(如果之前选择了epoll)
void *evbase = base->evbase;//epoll.c的epollop对象
struct timeval tv;
struct timeval *tv_p;
int res, done;
/* clear time cache */
base->tv_cache.tv_sec = 0;//清除时间缓存,好让下面的gettime获得当前系统时间而不是获得缓存的时间
if (base->sig.ev_signal_added)
evsignal_base = base;//该变量也是一个全局的变量,赋值后关于信号的一些操作默认用到这个base
done = 0;
while (!done) {
/* Terminate the loop if we have been asked to */
if (base->event_gotterm) {//这两个是用来中断循环的标识
base->event_gotterm = 0;
break;
}
if (base->event_break) {
base->event_break = 0;
break;
}
timeout_correct(base, &tv);//如果使用了monotonic时钟类型则这个函数就没用了
tv_p = &tv;
if (!base->event_count_active && !(flags & EVLOOP_NONBLOCK)) {//如果没有就绪的事件,则获得接下来需要最小等待时间,用作epoll_wait的时间参数
timeout_next(base, &tv_p);
} else {
/*
* if we have active events, we just poll new events
* without waiting.
*/
evutil_timerclear(&tv);//有就绪事件则无需等待epoll_wait,时间设置为0
}
/* If we have no events, we just exit *///无事件注册了则退出循环
if (!event_haveevents(base)) {
event_debug(("%s: no events registered.", __func__));
return (1);
}
/* update last old time */
gettime(base, &base->event_tv);//如果使用了monotonic时钟,则这个也没什么意义
/* clear time cache */
base->tv_cache.tv_sec = 0;
res = evsel->dispatch(base, evbase, tv_p);//内部使用epoll_wait()等待事件,不过仅仅处理读写事件,信号事件在evsignal_process()函数处理
if (res == -1)
return (-1);
gettime(base, &base->tv_cache);//获得当前时间,更新缓存,缓存的作用是无需调用系统调用获得时间,省时
timeout_process(base);//检查小根堆的事件是否到时,并进行删除过期事件和插入就绪链表的动作
if (base->event_count_active) {//有就绪事件则调用事件注册的回调函数
event_process_active(base);
if (!base->event_count_active && (flags & EVLOOP_ONCE))
done = 1;
} else if (flags & EVLOOP_NONBLOCK)
done = 1;
}
/* clear time cache */
base->tv_cache.tv_sec = 0;
event_debug(("%s: asked to terminate loop.", __func__));
return (0);
}
[libevent]event_base_loop()
最新推荐文章于 2023-09-26 00:47:39 发布