event_add是第三个函数,函数参数ev是指向要注册的事件,tv是超时时间,
函数将ev注册到ev->ev_base上,事件类型由ev->ev_events指明。如果注册成功,ev讲被插入到已经注册链表中,如果tv不是null,则会同时注册定时事件,将ev添加到timer堆上,其中的巧妙之处请看以下分析
int
720 event_add(struct event *ev, const struct timeval *tv)
721 {
722 struct event_base *base = ev->ev_base; // 要注册到的event_base
723 const struct eventop *evsel = base->evsel; //base使用的系统I/O策略
/**
新的timer事件,调用tiamer heap接口在堆上预留以一个位置
这样能保证该操作的原子性
向系统I./O机制注册可能会失败,而当在堆上预留成功后,
定时事件的添加讲肯定不会失败,
而预留位置的可能结果是堆扩充,但是内部元素并不会改变
*/
724 void *evbase = base->evbase;
725 int res = 0;
726
727 event_debug((
728 "event_add: event: %p, %s%s%scall %p",
729 ev,
730 ev->ev_events & EV_READ ? "EV_READ " : " ",
731 ev->ev_events & EV_WRITE ? "EV_WRITE " : " ",
732 tv ? "EV_TIMEOUT " : " ",
733 ev->ev_callback));
734
735 assert(!(ev->ev_flags & ~EVLIST_ALL));
736
737 /*
738 * prepare for timeout insertion further below, if we get a
739 * failure on any step, we should not change any state.
740 */
741 if (tv != NULL && !(ev->ev_flags & EVLIST_TIMEOUT)) {
742 if (min_heap_reserve(&base->timeheap,
743