event_add

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);          /*  插入到事件列表  */  
    }  
   }  

 

支持Libevent运转的就是一个大循环,这个主循环体现在event_base_loop(Event.c/1533)函数里,该函数的执行流程如下:


图1 event_base_loop主循环
        上图的简单描述就是:
        (1)校正系统当前时间。
        (2)将当前时间与存放时间的最小堆中的时间依次进行比较,将所有时间小于当前时间的定时器事件从堆中取出来加入到活动事件队列中。
        (3)调用I/O封装(比如:Epoll)的事件分发函数dispatch函数,以当前时间与时间堆中的最小值之间的差值(最小堆取最小值复杂度为O(1))作为Epoll/epoll_wait(Epoll.c/dispatch/407)的timeout值,在其中将触发的I/O和信号事件加入到活动事件队列中。
        (4)调用函数event_process_active(Event.c/1406)遍历活动事件队列,依次调用注册的回调函数处理相应事件。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值