1. 程式人生 > >Libev 官方文件學習筆記

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_XXXev_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, 事件的掩碼值。可能的掩碼值有:

  • EV_READ

  • EV_WRITE

  • EV_TIMER:ev_timer 超時

  • EV_PERIODIC:ev_periodic 超時

  • EV_SIGNAL:某執行緒接收了 ev_signal 中指定的 signal

  • EV_CHILD

    :ev_child 中指定的 pid 獲得了一個狀態變化

  • EV_STAT:ev_stat 中指定的 path 的屬性修改了

  • EV_IDLE:ev_idle watcher 發現無事可做

  • EV_PREPAREEV_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_eventev_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 相同。

系列篇