多多色-多人伦交性欧美在线观看-多人伦精品一区二区三区视频-多色视频-免费黄色视屏网站-免费黄色在线

國內最全IT社區平臺 聯系我們 | 收藏本站
阿里云優惠2
您當前位置:首頁 > php框架 > 框架設計 > [libevent源碼分析] event_base_dispatch

[libevent源碼分析] event_base_dispatch

來源:程序員人生   發布時間:2015-03-27 07:58:06 閱讀次數:3525次

分析下事件循環 event_base_dispatch

int event_base_dispatch(struct event_base *event_base) { return (event_base_loop(event_base, 0)); } 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; /* clear time cache */ base->tv_cache.tv_sec = 0; if (base->sig.ev_signal_added) evsignal_base = base; //如果說當前ev_base已加入了信號事件,那末就把ev_signal_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 == ⑴) { errno = EINTR; return (⑴); } } } /* 這個函數就是獲得當前時間保存在tv中,如果時間變化了,需要更新時間最小堆中的時間,主要是獲得當前時間 */ timeout_correct(base, &tv); tv_p = &tv; 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); } /* If we have no events, we just exit */ if (!event_haveevents(base)) { event_debug(("%s: no events registered.", __func__)); return (1); } /* update last old time */ gettime(base, &base->event_tv); /* clear time cache */ base->tv_cache.tv_sec = 0;//清0是為了當有激活事件的時候,獲得系統最新時間 res = evsel->dispatch(base, evbase, tv_p); if (res == ⑴) return (⑴); 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; } /* clear time cache */ base->tv_cache.tv_sec = 0; event_debug(("%s: asked to terminate loop.", __func__)); return (0); }
1 關于時間更新問題,主要利用了ev_base->tv_cache 和 ev_base->event_tv這兩個時間,前者是事件觸發錢的tv_cache時間(第1次不是)
 后者是激活事件放入到激活鏈表后的時間,如果tv_cache小于event_tv那末時間就被更新了,在timeout_correct中處理

static void timeout_correct(struct event_base *base, struct timeval *tv) { struct event **pev; unsigned int size; struct timeval off; if (use_monotonic) return; /* 這里如果返回表示時間未更新 */ /* Check if time is running backwards */ gettime(base, tv); if (evutil_timercmp(tv, &base->event_tv, >=)) { base->event_tv = *tv; return; } event_debug(("%s: time is running backwards, corrected", __func__)); evutil_timersub(&base->event_tv, tv, &off); /* * We can modify the key element of the node without destroying * the key, beause we apply it to all in the right order. */ pev = base->timeheap.p; size = base->timeheap.n; for (; size-- > 0; ++pev) { struct timeval *ev_tv = &(**pev).ev_timeout; evutil_timersub(ev_tv, &off, ev_tv); } }

2 以epoll為例。 evsel->dispatch就是調用epollop中epoll的dispatch函數

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 = ⑴; if (tv != NULL) 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 == ⑴) { if (errno != EINTR) { event_warn("epoll_wait"); return (⑴); } 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; 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); }

3 剩下的就是遍歷激活鏈表處理事件回調

static void event_process_active(struct event_base *base) { struct event *ev; struct event_list *activeq = NULL; int i; short ncalls; for (i = 0; i < base->nactivequeues; ++i) { if (TAILQ_FIRST(base->activequeues[i]) != NULL) { activeq = base->activequeues[i]; break; } } assert(activeq != NULL); for (ev = TAILQ_FIRST(activeq); ev; ev = TAILQ_FIRST(activeq)) { if (ev->ev_events & EV_PERSIST) event_queue_remove(base, ev, EVLIST_ACTIVE); else event_del(ev); /* Allows deletes to work */ ncalls = ev->ev_ncalls; ev->ev_pncalls = &ncalls; while (ncalls) { ncalls--; ev->ev_ncalls = ncalls; (*ev->ev_callback)((int)ev->ev_fd, ev->ev_res, ev->ev_arg); if (event_gotsig || base->event_break) return; } } }


libeven 全部源碼分析和sample都在我的 githup

生活不易,碼農辛苦
如果您覺得本網站對您的學習有所幫助,可以手機掃描二維碼進行捐贈
程序員人生
------分隔線----------------------------
分享到:
------分隔線----------------------------
關閉
程序員人生
主站蜘蛛池模板: 日本欧美人xxxxx在线观看 | 亚洲欧美一区二区三区九九九 | 欧美日韩中文一区 | 好看欧美视频高清va | 亚洲人成网站在线观看播放青青 | 欧美日韩一区二区在线观看视频 | 91精品久久久久久久久久小网站 | 久久婷婷一区二区三区 | 亚洲国产成人99精品激情在线 | 亚洲一区二区三区在线网站 | 最新自拍偷拍 | 一区二区三 | 国产肥老妇 | 久久久久毛片成人精品 | 久久久久成人精品一区二区 | 一牛精品视频在线观看免费 | 精品剧情v国产在免费线观看 | 中文字幕色站 | 亚洲国产精品久久久久网站 | 亚洲精品久久久久久下一站 | 欧美x性| 久久亚洲在线 | 国产成人美女福利在线观看 | 成人精品一区二区久久 | 18一20岁一级毛片 | 美女毛片网站 | 亚洲精品一区二区乱码在线观看 | 一级日韩一级欧美 | 日韩免费高清 | 亚洲国产精品二区久久 | 性做久久 | 欧美成人免费在线 | 亚洲图片 自拍 | 欧美日韩亚洲综合在线一区二区 | 免费91最新地址永久入口 | 欧美一区二区三区视频 | 欧美综合自拍亚洲综合 | 在线视频精品播放 | 一区二区高清视频 | 欧美一级毛片无遮无挡 | 国产美女主播一级成人毛片 |