-
int
-
event_add(struct event *ev, const struct timeval *tv)
-
{
-
struct event_base *base = ev->ev_base;
-
const struct eventop *evsel = base->evsel;
-
void *evbase = base->evbase;
-
int res = 0;
-
-
event_debug((
-
"event_add: event: %p, %s%s%scall %p",
-
ev,
-
ev->ev_events & EV_READ ? "EV_READ " : " ",
-
ev->ev_events & EV_WRITE ? "EV_WRITE " : " ",
-
tv ? "EV_TIMEOUT " : " ",
-
ev->ev_callback));
-
-
assert(!(ev->ev_flags & ~EVLIST_ALL)); //ev_flags必须是EVLIST_ALL中的一个
-
-
/*
-
* prepare for timeout insertion further below, if we get a
-
* failure on any step, we should not change any state.
-
*/
-
if (tv != NULL && !(ev->ev_flags & EVLIST_TIMEOUT)) { //tv不为NULl并且ev的链表类型不属于EVLIST_TIMEOUT链表
-
if (min_heap_reserve(&base->timeheap,
-
1 + min_heap_size(&base->timeheap)) == -1) //检测最小堆是否需要增加空间
-
return (-1); /* ENOMEM == errno */ //返回内存不足的错误Error_No_Memory
-
}
-
-
if ((ev->ev_events & (EV_READ|EV_WRITE|EV_SIGNAL)) && //ev_events是EV_READ,EV_WRITE,EV_SIGNAL其中一个
-
!(ev->ev_flags & (EVLIST_INSERTED|EVLIST_ACTIVE))) { //ev_flags不是EVLIST_INSERTED,EVLIST_ACTIVE其中一个(ev的链表类型不属于EVLIST_INSERTED,EVLIST_ACTIVE)
-
res = evsel->add(evbase, ev); //调用接口的add()函数
-
if (res != -1)
-
event_queue_insert(base, ev, EVLIST_INSERTED); //加入到base的eventqueue链表
-
}
-
-
/*
-
* we should change the timout state only if the previous event
-
* addition succeeded.
-
*/
-
if (res != -1 && tv != NULL) { //前面的过程成功,并且tv不为NULL,这里专门处理超时事件与定时器事件
-
struct timeval now;
-
-
/*
-
* we already reserved memory above for the case where we
-
* are not replacing an exisiting timeout.
-
*/
-
if (ev->ev_flags & EVLIST_TIMEOUT) //ev_flag为EVLIST_TIMEOUT,则从小根堆中删除ev
-
event_queue_remove(base, ev, EVLIST_TIMEOUT); //
-
-
/* Check if it is active due to a timeout. Rescheduling
-
* this timeout before the callback can be executed
-
* removes it from the active list. */
-
if ((ev->ev_flags & EVLIST_ACTIVE) && //活动event超时了
-
(ev->ev_res & EV_TIMEOUT)) {
-
/* See if we are just active executing this
-
* event in a loop
-
*/
-
if (ev->ev_ncalls && ev->ev_pncalls) {
-
/* Abort loop */
-
*ev->ev_pncalls = 0;
-
}
-
-
event_queue_remove(base, ev, EVLIST_ACTIVE);//从active链表中移除
-
}
-
-
gettime(base, &now); //得到现在的时间
-
evutil_timeradd(&now, tv, &ev->ev_timeout); //修改event的timeout时间
-
-
event_debug((
-
"event_add: timeout in %ld seconds, call %p",
-
tv->tv_sec, ev->ev_callback));
-
-
event_queue_insert(base, ev, EVLIST_TIMEOUT);//插入到timeout链表
-
}
-
-
return (res);
-
}
event_add()函数实现了把ev加入到eventbase的链表之中,主要有以下步骤:
(1) 如果指定的该ev的超时时间tv不为空,并且该ev不是在
EVLIST_TIMEOUT链表中,就在最小堆中为该ev申请位置。实际上
EVLIST_TIMEOUT链表是用最小堆数据结构实现的
(2) 如果ev的事件类型属于EV_READ|EV_WRITE|EV_SIGNAL,并且ev不在EVLSIT_INSERTED|EVLIST_ACTIVE中,则把该ev加入到EV_INSERTED链表中
(3) 如果指定的该ev的超时时间tv不为空,如果ev已经在TIME_OUT链表之中,则把ev从
EVLIST_TIMEOUT链表中移除。
(4)
如果指定的该ev的超时时间tv不为空,重新设定ev的超时时间,并把该ev插入到EVLIST_TIMEOUT链表
上面的规则概括出来,会出现下面几种情况
如果是IO事件,或者是SIGNAL事件,并且指定了超时时间,则
(1) 这个事件首先会进入EVLIST_INSERTED链表之中
(2) 这个事件会被重新计算超时时间,并进入ELIST_TIMEOUT链表之中
如果是IO事件,或者是SIGNAL事件,未指定超时时间,则
(1) 这个事件会进入EVLIST_INSERTED链表之中
如果是TIMEOUT事件(TIMEOUT事件必定指定了超时时间)
(1)
这个事件会被重新计算超时时间,并进入ELIST_TIMEOUT链表之中
event_add()
|----event_queue_insert() //插入ev到指定链表中
-
void
-
event_queue_insert(struct event_base *base, struct event *ev, int queue)
-
{
-
if (ev->ev_flags & queue) {//ev已经在queue指定的链表之中,则继续执行
-
/* Double insertion is possible for active events */
-
if (queue & EVLIST_ACTIVE) //queue==EVLIST_ACTIVE,直接返回
-
return;
-
-
event_errx(1, "%s: %p(fd %d) already on queue %x", __func__,
-
ev, ev->ev_fd, queue);
-
}
-
-
if (~ev->ev_flags & EVLIST_INTERNAL) //ev_flag不包含EVLIST_INTERNAL,则base->event_count++
-
base->event_count++;
-
-
ev->ev_flags |= queue; //ev_flag增加queue,记录ev所处的链表类型
-
switch (queue) {
-
case EVLIST_INSERTED:
-
TAILQ_INSERT_TAIL(&base->eventqueue, ev, ev_next);// 加入到eventqueue链表
-
break;
-
case EVLIST_ACTIVE:
-
base->event_count_active++; //active的事件数目+1
-
TAILQ_INSERT_TAIL(base->activequeues[ev->ev_pri],//加入到activequeue[i]链表
-
ev,ev_active_next);
-
break;
-
case EVLIST_TIMEOUT: {
-
min_heap_push(&base->timeheap, ev);//加入到最小堆
-
break;
-
}
-
default:
-
event_errx(1, "%s: unknown queue %x", __func__, queue);
-
}
-
}
event_add()
|----event_queue_remove() //从指定链表中移除ev
-
void
-
event_queue_remove(struct event_base *base, struct event *ev, int queue)
-
{
-
if (!(ev->ev_flags & queue)) //如果ev_flags不包含queue,则退出,这里可以理解为从ev_flag中取出queue
-
event_errx(1, "%s: %p(fd %d) not on queue %x", __func__,
-
ev, ev->ev_fd, queue);
-
-
if (~ev->ev_flags & EVLIST_INTERNAL) //ev_flags不包含EVLIST_INTERNAL,则event_count--
-
base->event_count--;
-
-
ev->ev_flags &= ~queue; //从ev_flags去除queue
-
switch (queue) {
-
case EVLIST_INSERTED:
-
TAILQ_REMOVE(&base->eventqueue, ev, ev_next); //从eventqueue中移除ev
-
break;
-
case EVLIST_ACTIVE:
-
base->event_count_active--;
-
TAILQ_REMOVE(base->activequeues[ev->ev_pri], //从activequeues[i]中移除ev
-
ev, ev_active_next);
-
break;
-
case EVLIST_TIMEOUT:
-
min_heap_erase(&base->timeheap, ev); //从最小堆中移除ev
-
break;
-
default:
-
event_errx(1, "%s: unknown queue %x", __func__, queue);
-
}
-
}
阅读(2310) | 评论(0) | 转发(0) |