請注意這是 libev 而不是 libevent 的文章!segmentfault
這篇文章是第二篇,主要講 libev 裏的 watcher 的一些基礎操做。服務器
本文地址:http://www.javashuo.com/article/p-erndlmxa-ch.html異步
如下是一段示意性的代碼,使用的是ev_io
:函數
static void my_cb (struct ev_loop *loop, ev_io *w, int revents) { ev_io_stop (w); ev_break (loop, EVBREAK_ALL); } some_main() { ... struct ev_loop *loop = ev_default_loop (0); ev_io stdin_watcher; ev_init (&stdin_watcher, my_cb); ev_io_set (&stdin_watcher, STDIN_FILENO, EV_READ); ev_io_start (loop, &stdin_watcher); ev_run (loop, 0); ... }
每個 watcher 類型有一個附屬的 watcher 結構體。(通常是struct ev_XXX
或ev_XXX
)
每個 watcher 結構都須要用ev_init
初始化,每個 watcher 都有對應的ev_XXX_set
函數、ev_XXX_start
函數、ev_XXX_stop
函數。在 ev_run 以前進行各個 watcher 的 ev_start。
只要 watcher 是 active,就不能再調用 init。
每一個 callback 都有三個參數:loop, watcher, 事件的掩碼值。可能的掩碼值有:oop
EV_READ
EV_WRITE
EV_TIMER
:ev_timer 超時EV_PERIODIC
:ev_periodic 超時EV_SIGNAL
:某線程接收了 ev_signal 中指定的 signalEV_CHILD
:ev_child 中指定的 pid 得到了一個狀態變化EV_STAT
:ev_stat 中指定的 path 的屬性修改了EV_IDLE
:ev_idle watcher 發現無事可作EV_PREPARE
, EV_CHECK
:全部 ev_prepare watchers 在 loop 開始收集事件前調用;全部ev_check watchers 則在之後調用。回調可在這兩個 watchers 中開始/中止相應的 watchers。EV_EMBED
:ev_embed watcherEV_CLEANUP
:event loop 即將被銷燬EV_ASYNC
:asuny watcher 已經被異步通知EV_CUSTOM
:不是 libev 發送的信號。參見ev_feed_event
EV_ERROR
:在 libev 內存不夠用時可能產生;fd 被外部關閉時也可能產生void ev_init (ev_TYPE *watcher, callback)
使用這個宏初始化 watcher。此外還須要調用相應的 ev_XXX_set
函數。參見下文:學習
void ev_TYPE_set (ev_TYPE *watcher, [args])
設置指定類型的 wetaher。init 函數必須在此以前被調用一次,此後能夠設置任意次的 set 函數。
不能對一個 active 的 watcher 調用此函數,但 pending 能夠。好比:ev_io w;
ev_init (&w, my_cb);
ev_io_set (&w, STDIN_FILENO, EV_READ);
線程
void ev_TYPE_set (ev_TYPE *watcher, callback, [args])
這個宏將 init 和 set 糅合在一塊兒使用指針
void ev_TYPE_start (loop, ev_TYPE *watcher)
開始(激活)指定的 watcher。若是 watcher 已是 active,則調用無效。code
void ev_TYPE_stop (loop, ev_TYPE *watcher)
中止 watcher,並清空 pending 狀態。若是要釋放一個 Watcher,最好都顯式地調用 stop。接口
bool ev_is_active (ev_TYPE *watcher)
若是 watcher 被執行了一次 start,而且未被 stop,則返回 true。
bool ev_is_pending (ev_TYPE *watcher)
當且僅當 watcher pending 時返回 true。(如:有未決的事件,可是 callback 未被調用)
callback ev_cb (ev_TYPE *watcher) void ev_set_cb (ev_TYPE *watcher, callback)
讀 / 寫 callback
void ev_set_priority (ev_TYPE *watcher, int priority) int ev_priority (ev_TYPE *watcher)
Priority 是一個介於EV_MAXPRI
(默認2)和EV_MIN_PRI
(默認-2)之間的值。數值越高越優先被調用。但除了 ev_idle,每個 watcher 都會被調用。
當 watcher 是 active 或 pending 時並不能修改。
實際上 priority 大於-2到2的範圍也是沒問題的。
void ev_invoke (loop, ev_TYPE *watcher, int revents);
使用指定的參數調用 callback
int ev_clear_pending (loop, ev_TYPE *watcher);
清除指定 watcher 的 pending 狀態,而且返回 revents 位。若是 watcher 不是 pending 則返回0
void ev_feed_event (loop, ev_TYPE *watcher, int revents)
模擬一個事件。參見ev_feed_fd_event
和ev_feed_signal_event
除了前文說起的 active 和 pending 狀態以外,本小節描述了更加詳細的 watcher 狀態。
initialized
:經過調用ev_TYPE_init
對 watcher 進行初始化,這是註冊到 loop 以前的必要步驟。能夠再次調用 ev_TYPE_init 進行操做。
started
/running
/active
:調用ev_TYPE_start
以後的狀態,而且開始等待事件。在這個狀態下,除了特別說起的少數狀況以外,它不能存取、移動、釋放,只能維持着對它的指針。
pending
:當 watcher 是 active 而且一個讓 watcher 感興趣的事件到來,那麼 watcher 進入 pending。這個狀態的 watcher 能夠 access,但不能存取、移動、釋放。
stopped
:調用ev_TYPE_stop
,此時狀態與 initialized 相同。
Libev 官方文檔學習筆記(1)——概述和 ev_loop
Libev 官方文檔學習筆記(2)——watcher 基礎(本文)
Libev 官方文檔學習筆記(3)——經常使用 watcher 接口
使用 libev 構建 TCP 響應服務器的簡單流程