libevent中,有三种事件,分别为IO(READ,WRITE),SIGNAL,TIMEOUT,对应于struct base中的三个链表和一个堆,其中ev_next用于串联全部(IO, SIGNAL) event,ev_active_next用于串联活动的事件(不一样的优先级对应于多个活动事件链表),ev_signal_next用于串联信号事件(每一个信号对应一个信号事件链表),min_heap_idx用于指向TIMEOUT事件在最小堆中的位置:
TAILQ_ENTRY (event) ev_next;
TAILQ_ENTRY (event) ev_active_next;
TAILQ_ENTRY (event) ev_signal_next;
unsigned int min_heap_idx; /* for managing timeouts */
event不能单独的存在,而是被event_base结构组织在一块儿。在event_base中,struct event_list **activequenes用于组织不一样优先级的活动事件,struct min_heap timeheap用于组织全部TIMEOUT事件,struct evsignal_info sig用于组织全部的SIGNAL事件。而struct event_list eventquene用于组织全部被插入的事件(包括IO,SIGNAL,不包含TIMEOUT)。
调用event_add添加事件时,若是是TIMEOUT事件,则添加到最小堆中;不然(IO,SIGNAL)先调用对应实现相关的add函数进行注册,而后调用event_queue_insert,将事件添加到eventquene中。
event_queue_insert函数根据插入类型quene选择不一样的链表进行插入。
代码以下:
int event_add(struct event *ev, const struct timeval *tv)
{
if (tv != NULL && !(ev->ev_flags & EVLIST_TIMEOUT)) {
if (min_heap_reserve(&base->timeheap,
1 + min_heap_size(&base->timeheap)) == -1)
return (-1); /* ENOMEM == errno */
}
if ((ev->ev_events & (EV_READ|EV_WRITE|EV_SIGNAL)) &&
!(ev->ev_flags & (EVLIST_INSERTED|EVLIST_ACTIVE))) {
res = evsel->add(evbase, ev);
/*调用select_add或者 epoll_add,他们根据事件是否为signal决定是否调用evsignal_add*/
if (res != -1)
event_queue_insert(base, ev, EVLIST_INSERTED);
/* 插入到事件列表 */
}
}
void event_queue_insert(struct event_base *base, struct event *ev, int queue)
{ //略过部分
switch (queue) {
case EVLIST_INSERTED:
TAILQ_INSERT_TAIL(&base->eventqueue, ev, ev_next);
break;
case EVLIST_ACTIVE:
base->event_count_active++;
TAILQ_INSERT_TAIL(base->activequeues[ev->ev_pri],
ev,ev_active_next);
break;
case EVLIST_TIMEOUT: {
min_heap_push(&base->timeheap, ev);
break;
}
}
SIGNAL事件:
全局变量 struct event_base *evsignal_base = NULL;
int evsignal_add(struct event *ev)
{
int evsignal;
struct event_base *base = ev->ev_base;
struct evsignal_info *sig = &ev->ev_base->sig;
evsignal = EVENT_SIGNAL(ev);
if (TAILQ_EMPTY(&sig->evsigevents[evsignal])) {
if (_evsignal_set_handler(
base, evsignal, evsignal_handler) == -1)
return (-1);
/* catch signals if they happen quickly */
evsignal_base = base;
/*
第一次添加信号时将ev_signal_added置为1,这样在主循环中就能够处理信号了。
不然当ev_signal_added为0时,不会处理信号
第一次添加信号事件时,该事件被调用了2次event_add,可是第二次调用的时候,
!(ev->ev_flags & (EVLIST_INSERTED|EVLIST_ACTIVE) 判断失败,
所以不会进行实际的插入操做
*/
if (!sig->ev_signal_added) {
if (event_add(&sig->ev_signal, NULL))
return (-1);
sig->ev_signal_added = 1;
}
}
/* multiple events may listen to the same signal */
TAILQ_INSERT_TAIL(&sig->evsigevents[evsignal], ev, ev_signal_next);
/*插入到对应的事件列表*/
return (0);
}
static void evsignal_handler(int sig)
{
evsignal_base->sig.evsigcaught[sig]++;
/* 将计数器加1 */
evsignal_base->sig.evsignal_caught = 1;
#ifndef HAVE_SIGACTION
signal(sig, evsignal_handler);
#endif
/* Wake up our notification mechanism */
send(evsignal_base->sig.ev_signal_pair[0], "a", 1, 0);
/*写入一个字节到socket,用于唤醒调用者来处理信号,see:evsignal_init*/
}
/* 用于在xx_dispatch中处理信号 */
void evsignal_process(struct event_base *base)
{
struct evsignal_info *sig = &base->sig;
struct event *ev, *next_ev;
sig_atomic_t ncalls;
int i;
base->sig.evsignal_caught = 0;
for (i = 1; i < NSIG; ++i) {
ncalls = sig->evsigcaught[i];
if (ncalls == 0)
continue;
for (ev = TAILQ_FIRST(&sig->evsigevents[i]);
ev != NULL; ev = next_ev) {
next_ev = TAILQ_NEXT(ev, ev_signal_next);
if (!(ev->ev_events & EV_PERSIST))
event_del(ev);
event_active(ev, EV_SIGNAL, ncalls);
/*将信号事件加入活动队列*/ } sig->evsigcaught[i] = 0; } }