前面的操作都完成之后,正式进入事件多路分发循环,在循环,Reactor框架等待事件的发生,然后寻找对应的事件处理器,然后调用对应的事件处理回调函数进行事件的处理,循环会一直运行,直到没有事件.
event_base_loop内部调用了event_process_active这个重要的函数:
执行事件多路分发循环的函数是event_base_dispatch,它调用的其实是event_base_loop,它定义如下:
/*
* 事件循环
* 首先调用io事件多路分发器的事件监听函数,等待事件
* 当有事件发生就依次处理之
*/
int
event_base_loop(struct event_base *base, int flags)
{
// 获取后端支持的io复用机制(一般来说linux是epoll,对于windows则是iocp)
const struct eventop *evsel = base->evsel;
// 时间
struct timeval tv;
// 指向上面的指针
struct timeval *tv_p;
int res, done, retval = 0;
/* Grab the lock. We will release it inside evsel.dispatch, and again
* as we invoke user callbacks. */
EVBASE_ACQUIRE_LOCK(base, th_base_lock);
// 一个event_base仅能运行一个事件循环
if (base->running_loop) {
event_warnx("%s: reentrant invocation. Only one event_base_loop"
" can run on each event_base at once.", __func__);
EVBASE_RELEASE_LOCK(base, th_base_lock);
return -1;
}
// 标记event_base已经开始运行
base->running_loop = 1;
// 清除event_base的系统时间缓存
// 存储时间缓存的目的就是避免多次的系统调用
clear_time_cache(base);
// 设置信号事件的event_base实例
if (base->sig.ev_signal_added && base->sig.ev_n_signals_added)
evsig_set_base(base);
done = 0;
#ifndef _EVENT_DISABLE_THREAD_SUPPORT
base->th_owner_id = EVTHREAD_GET_ID();
#endif
base->event_gotterm = base->event_break = 0;
// 事件循环
while (!done)
{
base->event_continue = 0;
/* Terminate the loop if we have been asked to */
if (base->event_gotterm)
{
break;
}
if (base->event_break)
{
break;
}
// 校准系统时间
timeout_correct(base, &tv);
tv_p = &tv;
// N_ACTIVE_CALLBACKS的作用是计算被激活的事件的数量
if (!N_ACTIVE_CALLBACKS(base) && !(flags & EVLOOP_NONBLOCK))
{
/*
* 获取时间堆上堆顶元素的超时值,即io复用系统调用本次应该设置的超时值
*/
timeout_next(base, &tv_p);
}
else
{
/*
* if we have active events, we just poll new events
* without waiting.
*/
/*
* 如果有就绪事件尚未处理,则将io复用系统调用的超时事件设置为0
* 这样io复用系统调用就能直接返回,程序就能够立即处理就绪事件了
*/
evutil_timerclear(&tv);
}
/* If we have no events, we just exit */
// 如果event_base中没有任何事件,则直接退出事件循环
if (!event_haveevents(base) && !N_ACTIVE_CALLBACKS(base))
{
event_debug(("%s: no events registered.", __func__));
retval = 1;
goto done;
}
/* update last old time */
// 更新系统事件
gettime(base, &base->event_tv);
// 清空时间缓存
clear_time_cache(base);
// 调用事件多路分发器的dispatch函数等待事件,将就绪的事件插入活动事件队列
res = evsel->dispatch(base, tv_p);
if (res == -1)
{
event_debug(("%s: dispatch returned unsuccessfully.",
__func__));
retval = -1;
goto done;
}
// 更新系统时间缓存
update_time_cache(base);
// 删除超时事件堆上的超时事件
timeout_process(base);
if (N_ACTIVE_CALLBACKS(base))
{
// 调用event_process_active函数依次处理就绪的事件和io事件
int n = event_process_active(base);
if ((flags & EVLOOP_ONCE)
&& N_ACTIVE_CALLBACKS(base) == 0
&& n != 0)
done = 1;
}
else if (flags & EVLOOP_NONBLOCK)
done = 1;
}
event_debug(("%s: asked to terminate loop.", __func__));
// 事件循环结束,清空事件缓存,并设置停止循环标志
done:
clear_time_cache(base);
base->running_loop = 0;
EVBASE_RELEASE_LOCK(base, th_base_lock);
return (retval);
}
event_base_loop内部调用了event_process_active这个重要的函数:
// 执行事件已经被激活的事件处理器对应的回调函数
static int
event_process_active(struct event_base *base)
{
/* Caller must hold th_base_lock */
struct event_list *activeq = NULL;
int i, c = 0;
// 遍历每一个被激活的队列
for (i = 0; i < base->nactivequeues; ++i)
{
// 如果该队列不为空
if (TAILQ_FIRST(&base->activequeues[i]) != NULL)
{
// 设置运行时优先级
base->event_running_priority = i;
activeq = &base->activequeues[i];
// 处理该队列内部的事件
c = event_process_active_single_queue(base, activeq);
if (c < 0)
{
base->event_running_priority = -1;
return -1;
}
else if (c > 0)
break; /* Processed a real event; do not
* consider lower-priority events */
/* If we get here, all of the events we processed
* were internal. Continue. */
}
}
// 对于延时的调用,等上面的激活队列都被扫描完毕才轮到它执行
event_process_deferred_callbacks(&base->defer_queue,&base->event_break);
// 设置运行时优先级
base->event_running_priority = -1;
return c;
}
event_process_active_single_queue用于处理单个队列当中的事件处理器
/*
* 处理单个激活队列内部的所有事件
* 返回有多少个非内部事件被处理
*/
static int
event_process_active_single_queue(struct event_base *base,
struct event_list *activeq)
{
struct event *ev;
// 非内部事件的数量
int count = 0;
EVUTIL_ASSERT(activeq != NULL);
// 遍历事件处理器队列中的每一个事件处理器
for (ev = TAILQ_FIRST(activeq); ev; ev = TAILQ_FIRST(activeq))
{
// 如果是永久事件,那么将它从激活事件队列中移除
// 否则,将他从所有的队列中删除
if (ev->ev_events & EV_PERSIST)
event_queue_remove(base, ev, EVLIST_ACTIVE);
else
event_del_internal(ev);
// 非内部事件
if (!(ev->ev_flags & EVLIST_INTERNAL))
++count;
event_debug((
"event_process_active: event: %p, %s%scall %p",
ev,
ev->ev_res & EV_READ ? "EV_READ " : " ",
ev->ev_res & EV_WRITE ? "EV_WRITE " : " ",
ev->ev_callback));
#ifndef _EVENT_DISABLE_THREAD_SUPPORT
base->current_event = ev;
base->current_event_waiters = 0;
#endif
// ev_closure指定event_base执行事件处理器的回调函数时候的行为
switch (ev->ev_closure)
{
case EV_CLOSURE_SIGNAL:
// 信号事件处理
event_signal_closure(base, ev);
break;
case EV_CLOSURE_PERSIST:
// 永久性事件处理
// 其实就是定时事件(定时器之类的)
event_persist_closure(base, ev);
break;
default:
case EV_CLOSURE_NONE:
EVBASE_RELEASE_LOCK(base, th_base_lock);
// 执行事件处理器的回调函数
(*ev->ev_callback)( ev->ev_fd, ev->ev_res, ev->ev_arg);
break;
}
EVBASE_ACQUIRE_LOCK(base, th_base_lock);
#ifndef _EVENT_DISABLE_THREAD_SUPPORT
base->current_event = NULL;
if (base->current_event_waiters)
{
base->current_event_waiters = 0;
EVTHREAD_COND_BROADCAST(base->current_event_cond);
}
#endif
// 如果event_base循环中断了,那么就直接返回
if (base->event_break)
return -1;
// 如果event_base跳过本次循环,那么剩余的事件也不再处理
if (base->event_continue)
break;
}
return count;
}
event_process_active_single_queue的内部分别调用了event_signal_closure和event_persist_closure,前者专门处理信号事件,后者处理永久性事件(即定时事件):
/*
* 信号处理
*/
static inline void
event_signal_closure(struct event_base *base, struct event *ev)
{
// 调用次数
short ncalls;
int should_break;
/* Allows deletes to work */
ncalls = ev->ev_ncalls;
if (ncalls != 0)
ev->ev_pncalls = &ncalls;
EVBASE_RELEASE_LOCK(base, th_base_lock);
// 执行ncalls次回调函数
while (ncalls) {
ncalls--;
ev->ev_ncalls = ncalls;
if (ncalls == 0)
ev->ev_pncalls = NULL;
// 调用回调函数
(*ev->ev_callback)(ev->ev_fd, ev->ev_res, ev->ev_arg);
EVBASE_ACQUIRE_LOCK(base, th_base_lock);
should_break = base->event_break;
EVBASE_RELEASE_LOCK(base, th_base_lock);
if (should_break) {
if (ncalls != 0)
ev->ev_pncalls = NULL;
return;
}
}
}
/*
* 专门处理永久性事件(即定时器事件)
*/
static inline void
event_persist_closure(struct event_base *base, struct event *ev)
{
// Define our callback, we use this to store our callback before it's executed
void (*evcb_callback)(evutil_socket_t, short, void *);
// Other fields of *ev that must be stored before executing
evutil_socket_t evcb_fd;
short evcb_res;
void *evcb_arg;
/* reschedule the persistent event if we have a timeout. */
// 重新调度这个定时器事件,如果这个事件有超时设置
if (ev->ev_io_timeout.tv_sec || ev->ev_io_timeout.tv_usec) {
/* If there was a timeout, we want it to run at an interval of
* ev_io_timeout after the last time it was _scheduled_ for,
* not ev_io_timeout after _now_. If it fired for another
* reason, though, the timeout ought to start ticking _now_. */
struct timeval
run_at, // 在某个时刻运行
relative_to, // 相对于超时时间
delay, // 延迟时间
now; // 当前时间
ev_uint32_t usec_mask = 0;
EVUTIL_ASSERT(is_same_common_timeout(&ev->ev_timeout,
&ev->ev_io_timeout));
// 获取当前时间
gettime(base, &now);
// 判断ev->ev_timeout是不是event_base的公共超时时间
if (is_common_timeout(&ev->ev_timeout, base))
{
delay = ev->ev_io_timeout;
usec_mask = delay.tv_usec & ~MICROSECONDS_MASK;
delay.tv_usec &= MICROSECONDS_MASK;
if (ev->ev_res & EV_TIMEOUT)
{
relative_to = ev->ev_timeout;
relative_to.tv_usec &= MICROSECONDS_MASK;
}
else
{
relative_to = now;
}
}
else
{
delay = ev->ev_io_timeout;
if (ev->ev_res & EV_TIMEOUT)
{
relative_to = ev->ev_timeout;
}
else
{
relative_to = now;
}
}
// 重新添加定时器
evutil_timeradd(&relative_to, &delay, &run_at);
if (evutil_timercmp(&run_at, &now, <))
{
/* Looks like we missed at least one invocation due to
* a clock jump, not running the event loop for a
* while, really slow callbacks, or
* something. Reschedule relative to now.
*/
// 重新添加定时器
evutil_timeradd(&now, &delay, &run_at);
}
run_at.tv_usec |= usec_mask;
// 事件添加
event_add_internal(ev, &run_at, 1);
}
// Save our callback before we release the lock
evcb_callback = ev->ev_callback;
evcb_fd = ev->ev_fd;
evcb_res = ev->ev_res;
evcb_arg = ev->ev_arg;
// Release the lock
EVBASE_RELEASE_LOCK(base, th_base_lock);
// Execute the callback
// 执行回调函数
(evcb_callback)(evcb_fd, evcb_res, evcb_arg);
}