libevent 源碼學習九 —— 集成定時器事件
阿新 • • 發佈:2019-05-03
激活 roc 計算 res 最大 沒有 time timeout loop 前言 : 與 Signal 相比,Timer 事件的集成會直觀和簡單很多
1. 集成到事件主循環
因為系統的 I/O 機制都允許程序制定一個最大的等待時間 timeout。就可以根據 Timer 事件的最小超時時間來設置系統 I/O 的 timeout時間。
2 代碼解析
if(!base -> event_count_active && !(flags & EVLOOP_NONBLOCK))
{// 根據 TImer 事件計算 evsel -> dispatch 的最大等待時間
timeout_next(base, &tv_p);
}
else
{// 如果還有活動事件,就不要等待,讓 evsel -> dispatch 立即返回
evutil_timerclear(&tv);
}
res = evsel -> dispatch(base, evbase, tv_p);
// 處理超時事件,插入到激活鏈表中
timeout_process(base)
timeout_next() 函數根據堆中具有最小超時值的事件和當前時間來計算等待時間。
static int timeout_next(struct event_base *base, struct timeval ** tv_p){
struct timeval now;
struct event *event;
struct timeval *tv = *tv_p;
// 堆的首元素具有最小的超時值
if((ev = min_heap_top(&base -> timeheap)) == NULL )
{// 如果沒有定時事件, 將等待時間設置為 NULL
*tv_p = NULl;
return 0;
}
// 取得當前時間
gettime(base, &now);
// 如果超時時間 <= 當前值,不能等待,需要立即返回
if(evutil_timercmp(&ev -> ev_timeout, &now, <=))
{
evutil_timerclear(tv);
return 0;
}
// 計算等待的時間 = 當前的時間 - 最小的超時時間
evutil_timersub(&ev -> ev_timeout, &now, tv);
return 0;
}
libevent 源碼學習九 —— 集成定時器事件