libevent 事件loop分析

来源:互联网 发布:淘宝客服怎么登陆千牛 编辑:程序博客网 时间:2024/04/29 09:07
event_init初 始化libevent事件全局对象current_base
初始化全局current_base是一个进程的个全局的变量
 
struct event_base *
event_init(void)
{
 struct  event_base *base = event_base_new();
 
 if (base !=  NULL)
  current_base = base;   <-----------
 
 return (base);
}
 
 
对libevent全局控制事件结构分析 
struct  event_base
{
 const struct eventop *evsel ;        对libevent操作函数集合结构ops
 void *evbase;
 int  event_count;  /* counts number of total events */  事件计数
 int event_count_active; /* counts number of active  events */
 
 int event_gotterm;  /* Set to terminate loop */    主循环停止标记
 int event_break;  /* Set to terminate loop  immediately */
 
 /* active event management */               活动事件管理
 struct event_list  **activequeues ;        活动事件链表
 int nactivequeues;
 
 /* signal handling info */             信号处理
 struct evsignal_info  sig;
 
 struct event_list eventqueue ;            事件队列

 struct  timeval event_tv ;                事件时间
 
 struct min_heap timeheap ;               时间堆
 
 struct timeval tv_cache ;
};
 
main函数事件循环函数
 
 400x /*
 401x  * Wait continously for events.  We exit  only if no events are left.
 402x  */
 403x
 404x int
 405x 
event_dispatch (void)
 406x  {
 407t>        return (event_loop(0));
 408x  }
 
 
事件循环包裹函数,将全局的变量current_base传入事件循环函数
int
event_loop (int  flags)
{
 return event_base_loop(current_base ,  flags);     <-----------
}
 
 
current_base参数传入了
int
event_base_loop (struct  event_base *base, int flags)
{
 const struct eventop *evsel =  base->evsel;
 void *evbase = base->evbase;
 struct timeval  tv;
 struct timeval *tv_p;
 int res, done;
 
 if (&base->sig.ev_signal_added)  如果加了信号处理
  evsignal_base = base;

 done = 0;
 while (!done) {
  /* Terminate the loop  if we have been asked to */
  if (base->event_gotterm) {
如果循环退出标记,退出
   base->event_gotterm =  0;
   break;
  }
 
  if (base->event_break) {  如果事件中断,退出
   base->event_break =  0;
   break;
  }
 
  /* You cannot use this interface for multi-threaded apps  */
  while (event_gotsig) {
   event_gotsig = 0;
   if (event_sigcb)  {
    res = (*event_sigcb)();
    if (res == -1) {
     errno =  EINTR;
     return (-1);
    }
   }
  }
  获取时间----比较当前事件时间和缓存累计时间
  timeout_correct (base, &tv );
 
  tv_p = &tv  获取时间epoll_wait的timeout时间  <-------------------------
 
    如果没有活动事件,指的是时间堆计数
  if  (!base->event_count_active && !(flags & EVLOOP_NONBLOCK))  {
   
timeout_next(base, & tv_p);
  }
  else
  {
   /*  有活动事件,轮询新事件
    * if we have active events, we  just poll new events
    * without waiting.
     */
   evutil_timerclear(&tv); tv值设置为0
  }
  
  /* If we have no events,  we just exit */
  if (!event_haveevents(base)) { 没有epoll事件则退出loop  (base->event_count >  0)  
   event_debug(("%s: no events registered.",  __func__));
   return (1);
  }
 
  /* update last old time */ 系统使用了tv_cache缓存累计时间,超过一秒更新到当前系统时间
  gettime(base, & base->event_tv);
 
  /* clear time cache */
  base->tv_cache.tv_sec =  0;
 开始进入epoll_wait函数,这里要注意到   tv_p  是上面 < -------------------------
  res = evsel->dispatch (base, evbase, tv_p ); 
 
  if (res == -1) 有错误则退出
   return  (-1);

  gettime(base, &base->tv_cache);
 
  timeout_process(base);
 
  if (base->event_count_active)  {
   event_process_active(base);
   if (!base->event_count_active && (flags & EVLOOP_ONCE))
    done = 1;
  } else if (flags & EVLOOP_NONBLOCK)
   done = 1;
 }
 
 event_debug(("%s: asked to terminate loop.",  __func__));
 return (0);
}
 
struct eventop {
 const char *name;
 void  *(*init)(struct event_base *);
 int (*add)(void *, struct event *);
 int  (*del)(void *, struct event *);
 
int (*dispatch)(struct event_base *, void *,  struct timeval *);
 void (*dealloc)(struct event_base *, void  *);
 /* set if we need to reinitialize the event base */
 int  need_reinit;
};
 
static int
epoll_dispatch (struct  event_base *base, void *arg, struct timeval *tv)
{
 struct epollop  *epollop = arg;
 struct epoll_event *events =  epollop->events;
 struct evepoll *evep ;
 int i, res, timeout  = -1;
 
 if (tv != NULL) 有超时时间,则换算成epoll_wait的时间
  timeout =  tv->tv_sec * 1000 + (tv->tv_usec + 999) / 1000;
 
 if (timeout > MAX_EPOLL_TIMEOUT_MSEC) {
  /* Linux  kernels can wait forever if the timeout is too big;
   * see comment on  MAX_EPOLL_TIMEOUT_MSEC. */
  timeout =  MAX_EPOLL_TIMEOUT_MSEC;
 }
 
 res =  epoll_wait(epollop->epfd, events, epollop->nevents, timeout ); <-------------------------
 
 if (res == -1) {
  if (errno != EINTR)  {
   event_warn("epoll_wait");
   return (-1);
  }
 
  evsignal_process (base);  信号处理函数
  return  (0);
 }
 else if (base->sig.evsignal_caught) {
  
evsignal_process(base);
 }
 
 event_debug(("%s: epoll_wait reports %d", __func__,  res));
 
 for (i = 0; i < res; i++) {
  int what =  events[i].events;
  struct event *evread = NULL, *evwrite =  NULL;
 
  evep= (struct evepoll  *)events[i].data.ptr; --------> struct evepoll* ----->  struct  event* rw
 
  if (what & (EPOLLHUP|EPOLLERR)) {
   evread =  evep->evread;
   evwrite = evep->evwrite;
  } else {
   if (what & EPOLLIN) {
    evread = evep ->evread;
   }
 
   if (what & EPOLLOUT) {
    evwrite  = evep ->evwrite;
   }
  }
 
  if (!(evread||evwrite))
   continue;
 
  if (evread != NULL)
   
event_active (evread, EV_READ,  1);
  if (evwrite != NULL)
   event_active (evwrite,  EV_WRITE, 1);
 }
 
 return (0);
}
0 0
原创粉丝点击