watcher初始化及啟動
ev_io:
初始化:
首先調用ev_init,設定watcher的初始化狀态,包括:active = 0, pending = 0, priority = 0以及回調函數;
再調用ev_io_set, 設定watcher所關注的檔案描述符(fd)以及事件(event)。
可以一次性調用ev_io_init進行上述兩項的設定。
啟動(ev_io_start):
判斷該watcher是否已經啟動,如果是,則直接傳回;
斷言該watcher關注的檔案句柄以及事件是否設定正确;
調用ev_start,對該watcher的優先級進行調整(系統預設的優先級範圍-2 ~ +2),設定watcher的狀态active為1,對相應消息循環中active watcher的個數加1;
調用array_needsize,為相應的消息循環配置設定儲存檔案描述符的ANFD anfds(數組以檔案描述符作為下标,相同檔案描述符的watcher以連結清單連接配接)空間,anfdmax記錄該數組的容量(需要時該容量自動擴充);
調用wlist_add,将watcher添加到相應檔案描述符的連結清單中;
調用fd_change,設定新增加或改變的檔案描述符,記錄在fdchanges數組中,fdchangecnt記錄數組下标,fdchangemax記錄數組容量(需要時該容量自動擴充)。
ev_timer:
初始化:
首先調用ev_init,設定watcher的初始化狀态,包括:active = 0, pending = 0, priority = 0以及回調函數;
再調用ev_timer_set, 設定watcher所關注的觸發時間點(at)以及重複次數(repeat)。
可以一次性調用ev_timer_init進行上述兩項的設定。
啟動(ev_timer_start):
判斷該watcher是否已經啟動,如果是,則直接傳回;
設定定時器實際觸發時間(at),at += loop->mn_now;
将該消息循環中定時器個數(timercnt)加1;
調用ev_start,對該watcher的優先級進行調整(系統預設的優先級範圍-2 ~ +2),設定watcher的狀态active為3(如果再向該消息循環中增加ev_timer,則下一個watcher的active值為上個watcher的active值加1),對相應消息循環中active watcher的個數加1;
調用array_needsize,為相應的消息循環配置設定儲存觸發時間的ANNE timers(數組以active值作為下标)堆空間,timermax記錄該數組的容量(需要時該容量自動擴充);
調用ANNE_w和ANNE_at_cache,設定ANNE結構體的w(watcher)以及at(觸發時間);
調用upheap,以watch的active值對timers堆進行排序。
ev_run:
增加該消息循環的調用次數,++(loop->loop_depth);
重新設定消息循環的狀态,loop->ev_break = EVBREAK_CANCEL;
在首次循環之前,調用所有pending watcher的回調;
循環:
如果使用了EVFLAG_FORKCHECK,則檢查是否産生了新的子程序;
如果檢測到新的子程序,則所有fork watchers加入到pending消息隊列并調用回調;
将所有的prepare watchers加入到pending消息隊列并調用回調;
如果調用了ev_break, 則消息循環結束;
如果産生了forked消息,重新設定核心狀态防止程序之間互相影響;
更新所有未解決的改變的核心狀态;
更新事件循環時間(ev_now());
計算該消息循環需要block或sleep多長時間或者不sleep(有激活的idle watchers,設定了EVRUN_NOWAIT或根據就沒有任何激活的watchers);
Sleep if the I/O and timer collect interval say so(?);
增加該消息循環循環次數,++(loop->loopcount);
阻塞程序,調用後端相應作業系統提供的事件檢測機制,等待事件發生;
将所有未解決的I/O(fd)事件加入到pending隊列;
更新事件循環時間(ev_now())并進行可能的時間調整;
将所有逾時的定時器(timer)加入到pending隊列;
将所有逾時的周期(periodics)加入到pending隊列;
将所有優先級大于pending隊列中的idle watchers加入到pending隊列;
将所有check watchers加入到pending隊列;
以反序調用所有加入pending隊列的watchers(例如:首先是check watchers)。信号和fork watchers是以I/O watcher的方式進行聲明,是以也會在這裡得到處理;
如果ev_break被調用,或設定了EVRUN_ONCE|EVRUN_NOWAIT,或沒有激活的watchers,則消息循環結束,否則繼續循環;
結束:
如果消息循環狀态為EVBREAK_ONE,則重新設定為EVBREAK_CANCEL;
減少該消息循環的調用次數,--(loop->loop_depth);
傳回,該消息循環中處于active狀态的watcher個數。