Libev 官方文件學習筆記
請注意這是 libev 而不是 libevent 的文章!
這篇文章是第二篇,主要講 libev 裡的 watcher 的一些基礎操作。
Watcher 解析
以下是一段示意性的程式碼,使用的是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
ev_XXX_set
函式、ev_XXX_start
函式、ev_XXX_stop
函式。在
ev_run 之前進行各個 watcher 的 ev_start。只要 watcher 是 active,就不能再呼叫 init。
每個 callback 都有三個引數:loop, watcher, 事件的掩碼值。可能的掩碼值有:
-
EV_READ
-
EV_WRITE
-
EV_TIMER
:ev_timer 超時 -
EV_PERIODIC
:ev_periodic 超時 -
EV_SIGNAL
:某執行緒接收了 ev_signal 中指定的 signal -
EV_CHILD
-
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 watcher -
EV_CLEANUP
:event loop 即將被銷燬 -
EV_ASYNC
:asuny watcher 已經被非同步通知 -
EV_CUSTOM
:不是 libev 傳送的訊號。參見ev_feed_event
-
EV_ERROR
:在 libev 記憶體不夠用時可能產生;fd 被外部關閉時也可能產生
通用 watcher 函式
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,則呼叫無效。
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
Watcher 狀態
除了前文提及的 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 相同。