libevent 源碼學習十一 —— 時間管理

前言 : 爲了支持定時器, Libevent 必須和系統時間打交道。主要涉及到時間的加減輔助函數、事件緩存、時間校訂和定時器堆的時間值調整等。 1 初始化檢測 Libevent 在初始化時會檢測系統時間的類型,經過調用函數 detect_monotonic() 完成,它經過調用 clock_gettime() 來檢測系統是否支持 monotonic 時鐘類型 static void detect_monotonic(){ #if defined(HAVE_CLOCK_GETTIME) &&defined(CLOCK_MONOTONIC) struct timespec ts; if(clock_gettime(CLOCK_MONOTONIC, &ts) == 0) use_monotonic = 1; #endif } 2 事件緩存 結構體 event_base 中的 tv_cache,用來記錄事件緩存。須要分析 gettime() 函數 static int gettime(struct event_base *base, struct timeval *tp){ // 若是 ev_cache 時間緩存已設置,就直接使用 if(base -> tv_cache.tv_sec){ *tp = base -> tv_cache; return 0; } // 若是支持 monotonic, 就用 clock_gettime 獲取 monotonic 時間 #if defined (HAVE_CLCOK_GETTIME) && defined(CLOCK_MONOTONIC) if(use_monotonic) { struct timespec ts; if (clock_gettime(CLOCK_MONOTONIC, &ts) == -1) return -1; tv -> tv_sec = ts.tv_sec; tp -> tv_usec = ts.tv_nsec / 1000; return 0; } #endif // 不然只能取得系統的當前時間 return evutil_gettimeofday(tp, NULL); } 在每次系統循環中,時間緩存 tv_cache 將會被相應的清空和重置。 時間 event_tv 指示了 dispatch()上次返回,也就是 I/O 事件就緒的時間。第一次循環時, tv_cache 被清空,所以 gettime() 獲取當前系統時間。然後會更新 tv_cache 時間 時間 tv_cache 在 dispatch() 返回後被設置爲系統時間,所以它緩存了本次 I/O 事件就緒的時間 : event_tv 3 時間校訂 若是系統不支持 monotonic 時間,用戶可能手動的調整時間,這就須要調整時間。由函數 tomeout_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; gettime(base, tv); //若是 tv < event_tv 代表用戶向前調整時間了,須要校訂 if(evutil_timercmp(tv, &base -> event_tv, >=)) { base -> event_tv = *tv; return ; } evutil_timersub(&base -> event_tv, tv, &off); // 調整定時事件小根堆 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); } // 更新 event_tv 爲 tv_cache base -> event_tv = *tv; }
相關文章
相關標籤/搜索