Chinaunix首页 | 论坛 | 博客
  • 博客访问: 91559
  • 博文数量: 31
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 380
  • 用 户 组: 普通用户
  • 注册时间: 2014-02-24 22:04
文章分类

全部博文(31)

文章存档

2014年(31)

我的朋友

分类: C/C++

2014-05-30 10:39:47




点击(此处)折叠或打开

  1. int
  2. event_add(struct event *ev, const struct timeval *tv)
  3. {
  4.     struct event_base *base = ev->ev_base;
  5.     const struct eventop *evsel = base->evsel;
  6.     void *evbase = base->evbase;
  7.     int res = 0;

  8.     event_debug((
  9.          "event_add: event: %p, %s%s%scall %p",
  10.          ev,
  11.          ev->ev_events & EV_READ ? "EV_READ " : " ",
  12.          ev->ev_events & EV_WRITE ? "EV_WRITE " : " ",
  13.          tv ? "EV_TIMEOUT " : " ",
  14.          ev->ev_callback));

  15.     assert(!(ev->ev_flags & ~EVLIST_ALL)); //ev_flags必须是EVLIST_ALL中的一个

  16.     /*
  17.      * prepare for timeout insertion further below, if we get a
  18.      * failure on any step, we should not change any state.
  19.      */
  20.     if (tv != NULL && !(ev->ev_flags & EVLIST_TIMEOUT)) { //tv不为NULl并且ev的链表类型不属于EVLIST_TIMEOUT链表
  21.         if (min_heap_reserve(&base->timeheap,    
  22.             1 + min_heap_size(&base->timeheap)) == -1)    //检测最小堆是否需要增加空间
  23.             return (-1); /* ENOMEM == errno */ //返回内存不足的错误Error_No_Memory
  24.     }

  25.     if ((ev->ev_events & (EV_READ|EV_WRITE|EV_SIGNAL)) && //ev_events是EV_READ,EV_WRITE,EV_SIGNAL其中一个
  26.      !(ev->ev_flags & (EVLIST_INSERTED|EVLIST_ACTIVE))) { //ev_flags不是EVLIST_INSERTED,EVLIST_ACTIVE其中一个(ev的链表类型不属于EVLIST_INSERTED,EVLIST_ACTIVE
  27.         res = evsel->add(evbase, ev);    //调用接口的add()函数
  28.         if (res != -1)
  29.             event_queue_insert(base, ev, EVLIST_INSERTED); //加入到base的eventqueue链表
  30.     }

  31.     /*
  32.      * we should change the timout state only if the previous event
  33.      * addition succeeded.
  34.      */
  35.     if (res != -1 && tv != NULL) {    //前面的过程成功,并且tv不为NULL,这里专门处理超时事件与定时器事件
  36.         struct timeval now;

  37.         /*
  38.          * we already reserved memory above for the case where we
  39.          * are not replacing an exisiting timeout.
  40.          */
  41.         if (ev->ev_flags & EVLIST_TIMEOUT) //ev_flag为EVLIST_TIMEOUT,则从小根堆中删除ev
  42.             event_queue_remove(base, ev, EVLIST_TIMEOUT);    //

  43.         /* Check if it is active due to a timeout. Rescheduling
  44.          * this timeout before the callback can be executed
  45.          * removes it from the active list. */
  46.         if ((ev->ev_flags & EVLIST_ACTIVE) && //活动event超时了
  47.          (ev->ev_res & EV_TIMEOUT)) {
  48.             /* See if we are just active executing this
  49.              * event in a loop
  50.              */
  51.             if (ev->ev_ncalls && ev->ev_pncalls) {
  52.                 /* Abort loop */
  53.                 *ev->ev_pncalls = 0;
  54.             }
  55.             
  56.             event_queue_remove(base, ev, EVLIST_ACTIVE);//从active链表中移除
  57.         }

  58.         gettime(base, &now);    //得到现在的时间
  59.         evutil_timeradd(&now, tv, &ev->ev_timeout); //修改event的timeout时间

  60.         event_debug((
  61.              "event_add: timeout in %ld seconds, call %p",
  62.              tv->tv_sec, ev->ev_callback));

  63.         event_queue_insert(base, ev, EVLIST_TIMEOUT);//插入到timeout链表
  64.     }

  65.     return (res);
  66. }
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到指定链表中

点击(此处)折叠或打开

  1. void
  2. event_queue_insert(struct event_base *base, struct event *ev, int queue)
  3. {
  4.     if (ev->ev_flags & queue) {//ev已经在queue指定的链表之中,则继续执行
  5.         /* Double insertion is possible for active events */
  6.         if (queue & EVLIST_ACTIVE) //queue==EVLIST_ACTIVE,直接返回
  7.             return;

  8.         event_errx(1, "%s: %p(fd %d) already on queue %x", __func__,
  9.              ev, ev->ev_fd, queue);
  10.     }

  11.     if (~ev->ev_flags & EVLIST_INTERNAL) //ev_flag不包含EVLIST_INTERNAL,则base->event_count++
  12.         base->event_count++;

  13.     ev->ev_flags |= queue; //ev_flag增加queue,记录ev所处的链表类型
  14.     switch (queue) {
  15.     case EVLIST_INSERTED:
  16.         TAILQ_INSERT_TAIL(&base->eventqueue, ev, ev_next);// 加入到eventqueue链表
  17.         break;
  18.     case EVLIST_ACTIVE:
  19.         base->event_count_active++;   //active的事件数目+1
  20.         TAILQ_INSERT_TAIL(base->activequeues[ev->ev_pri],//加入到activequeue[i]链表
  21.          ev,ev_active_next);
  22.         break;
  23.     case EVLIST_TIMEOUT: {
  24.         min_heap_push(&base->timeheap, ev);//加入到最小堆
  25.         break;
  26.     }
  27.     default:
  28.         event_errx(1, "%s: unknown queue %x", __func__, queue);
  29.     }
  30. }




event_add()
    |----event_queue_remove()    //从指定链表中移除ev

点击(此处)折叠或打开

  1. void
  2. event_queue_remove(struct event_base *base, struct event *ev, int queue)
  3. {
  4.     if (!(ev->ev_flags & queue)) //如果ev_flags不包含queue,则退出,这里可以理解为从ev_flag中取出queue
  5.         event_errx(1, "%s: %p(fd %d) not on queue %x", __func__,
  6.              ev, ev->ev_fd, queue);

  7.     if (~ev->ev_flags & EVLIST_INTERNAL) //ev_flags不包含EVLIST_INTERNAL,则event_count--
  8.         base->event_count--;

  9.     ev->ev_flags &= ~queue; //从ev_flags去除queue
  10.     switch (queue) {
  11.     case EVLIST_INSERTED:
  12.         TAILQ_REMOVE(&base->eventqueue, ev, ev_next);    //从eventqueue中移除ev
  13.         break;
  14.     case EVLIST_ACTIVE:
  15.         base->event_count_active--;
  16.         TAILQ_REMOVE(base->activequeues[ev->ev_pri],    //从activequeues[i]中移除ev
  17.          ev, ev_active_next);
  18.         break;
  19.     case EVLIST_TIMEOUT:
  20.         min_heap_erase(&base->timeheap, ev);    //从最小堆中移除ev
  21.         break;
  22.     default:
  23.         event_errx(1, "%s: unknown queue %x", __func__, queue);
  24.     }
  25. }










阅读(2226) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~