翻譯:libevent參考手冊第四章:與事件一起工作 (六) (轉)
libevent的基本操作單元是事件。每個事件代表一組條件的集合,這些條件包括:
v 檔案描述符已經就緒,可以讀取或者寫入
v 檔案描述符變為就緒狀態,可以讀取或者寫入(僅對於邊沿觸發IO)
v 超時事件
v 發生某訊號
v 使用者觸發事件
所有事件具有相似的生命週期。呼叫libevent函式設定事件並且關聯到event_base之後,事件進入“已初始化(initialized)”狀態。此時可以將事件新增到event_base中,這使之進入“未決(pending)”狀態。在未決狀態下,如果觸發事件的條件發生(比如說,檔案描述符的狀態改變,或者超時時間到達),則事件進入“啟用(active)”狀態,(使用者提供的)事件回撥函式將被執行。如果配置為“
1 構造事件物件
1.1 建立事件
使用event_new()介面建立事件。
介面
#define EV_TIMEOUT 0x01#define EV_READ 0x02#define EV_WRITE 0x04#define EV_SIGNAL 0x08#define EV_PERSIST 0x10#define EV_ET 0x20
typedef void (* event_callback_fn)(evutil_socket_t, short, void*);
structevent*event_new(struct event_base *base, evutil_socket_t fd,
short what, event_callback_fn cb,
void*arg);
void event_free(structevent*event);
event_new()試圖分配和構造一個用於base的新的事件。what引數是上述標誌的集合。如果fd非負,則它是將被觀察其讀寫事件的檔案。事件被啟用時,libevent將呼叫cb函式,傳遞這些引數:檔案描述符fd,表示所有被觸發事件的位欄位,以及構造事件時的arg引數。
發生內部錯誤,或者傳入無效引數時,event_new()將返回NULL。
所有新建立的事件都處於已初始化和非未決狀態,呼叫event_add()可以使其成為未決的。
要釋放事件,呼叫event_free()。對未決或者啟用狀態的事件呼叫event_free()是安全的:在釋放事件之前,函式將會使事件成為非啟用和非未決的。
示例
#include <event2/event.h>void cb_func(evutil_socket_t fd, short what, void*arg)
{
constchar*data = arg;
printf("Got an event on socket %d:%s%s%s%s [%s]",
(int) fd,
(what&EV_TIMEOUT) ?" timeout" : "",
(what&EV_READ) ?" read" : "",
(what&EV_WRITE) ?" write" : "",
(what&EV_SIGNAL) ?" signal" : "",
data);
}
void main_loop(evutil_socket_t fd1, evutil_socket_t fd2)
{
structevent*ev1, *ev2;
struct timeval five_seconds = {5,0};
struct event_base *base= event_base_new();
/* The caller has already set up fd1, fd2 somehow, and make them
nonblocking. */
ev1 = event_new(base, fd1, EV_TIMEOUT|EV_READ|EV_PERSIST, cb_func,
(char*)"Reading event");
ev2 = event_new(base, fd2, EV_WRITE|EV_PERSIST, cb_func,
(char*)"Writing event");
event_add(ev1, &five_seconds);
event_add(ev2, NULL);
event_base_dispatch(base);
}
上述函式定義在<event2/event.h>中,首次出現在libevent 2.0.1-alpha版本中。event_callback_fn型別首次在2.0.4-alpha版本中作為typedef出現。
1.2 事件標誌
v EV_TIMEOUT
這個標誌表示某超時時間流逝後事件成為啟用的。構造事件的時候,EV_TIMEOUT標誌是被忽略的:可以在新增事件的時候設定超時,也可以不設定。超時發生時,回撥函式的what引數將帶有這個標誌。
v EV_READ
表示指定的檔案描述符已經就緒,可以讀取的時候,事件將成為啟用的。
v EV_WRITE
表示指定的檔案描述符已經就緒,可以寫入的時候,事件將成為啟用的。
v EV_SIGNAL
用於實現訊號檢測,請看下面的“構造訊號事件”節。
v EV_PERSIST
表示事件是“持久的”,請看下面的“關於事件永續性”節。
v EV_ET
表示如果底層的event_base後端支援邊沿觸發事件,則事件應該是邊沿觸發的。這個標誌影響EV_READ和EV_WRITE的語義。
從2.0.1-alpha版本開始,可以有任意多個事件因為同樣的條件而未決。比如說,可以有兩個事件因為某個給定的fd已經就緒,可以讀取而成為啟用的。這種情況下,多個事件回撥被執行的次序是不確定的。
這些標誌定義在<event2/event.h>中。除了EV_ET在2.0.1-alpha版本中引入外,所有標誌從1.0版本開始就存在了。
1.3 關於事件永續性
預設情況下,每當未決事件成為啟用的(因為fd已經準備好讀取或者寫入,或者因為超時),事件將在其回撥被執行前成為非未決的。如果想讓事件再次成為未決的,可以在回撥函式中再次對其呼叫event_add()。
然而,如果設定了EV_PERSIST標誌,事件就是持久的。這意味著即使其回撥被啟用,事件還是會保持為未決狀態。如果想在回撥中讓事件成為非未決的,可以對其呼叫event_del()。
每次執行事件回撥的時候,持久事件的超時值會被複位。因此,如果具有EV_READ|EV_PERSIST標誌,以及5秒的超時值,則事件將在以下情況下成為啟用的:
v 套接字已經準備好被讀取的時候
v 從最後一次成為啟用的開始,已經逝去5秒
1.4 只有超時的事件
為使用方便,libevent提供了一些以evtimer_開頭的巨集,用於替代event_*呼叫來操作純超時事件。使用這些巨集能改進程式碼的清晰性。
介面
#define evtimer_new(base, callback, arg) \
event_new((base), -1, 0, (callback), (arg))
#define evtimer_add(ev, tv) \
event_add((ev),(tv))
#define evtimer_del(ev) \
event_del(ev)
#define evtimer_pending(ev, what, tv_out) \
event_pending((ev), (what), (tv_out))除了evtimer_new()首次出現在2.0.1-alpha版本中之外,這些巨集從0.6版本就存在了。
1.5 構造訊號事件
libevent也可以監測POSIX風格的訊號。要構造訊號處理器,使用:
介面
#define evsignal_new(base, signum, callback, arg) \
event_new(base, signum, EV_SIGNAL|EV_PERSIST, cb, arg)除了提供一個訊號編號代替檔案描述符之外,各個引數與event_new()相同。
示例
structevent*hup_event;
struct event_base *base= event_base_new();
/* call sighup_function on a HUP signal */
hup_event = evsignal_new(base, SIGHUP, sighup_function, NULL);注意:訊號回撥是訊號發生後在事件迴圈中被執行的,所以可以安全地呼叫通常不能在POSIX風格訊號處理器中使用的函式。
警告:不要在訊號事件上設定超時,這可能是不被支援的。[待修正:真是這樣的嗎?]
libevent也提供了一組方便使用的巨集用於處理訊號事件:
介面
#define evsignal_add(ev, tv) \
event_add((ev),(tv))
#define evsignal_del(ev) \
event_del(ev)
#define evsignal_pending(ev, what, tv_out) \
event_pending((ev), (what), (tv_out))
evsignal_*巨集從2.0.1-alpha版本開始存在。先前版本中這些巨集叫做signal_add()、signal_del()等等。
關於訊號的警告
在當前版本的libevent和大多數後端中,每個程序任何時刻只能有一個event_base可以監聽訊號。如果同時向兩個event_base新增訊號事件,即使是不同的訊號,也只有一個event_base可以取得訊號。
kqueue後端沒有這個限制。
1.6 設定不使用堆分配的事件
出於效能考慮或者其他原因,有時需要將事件作為一個大結構體的一部分。對於每個事件的使用,這可以節省:
v 記憶體分配器在堆上分配小物件的開銷
v 對event結構體指標取值的時間開銷
v 如果事件不在快取中,因為可能的額外快取丟失而導致的時間開銷
對於大多數應用來說,這些開銷是非常小的。所以,除非確定在堆上分配事件導致了嚴重的效能問題,應該堅持使用event_new()。如果將來版本中的event結構體更大,不使用event_new()可能會導致難以診斷的錯誤。
不在堆上分配event具有破壞與其他版本libevent二進位制相容性的風險:其他版本中的event結構體大小可能不同。
介面
int event_assign(structevent*event, struct event_base *base,
evutil_socket_t fd, short what,
void (*callback)(evutil_socket_t, short, void*), void*arg);除了event引數必須指向一個未初始化的事件之外,event_assign()的引數與event_new()的引數相同。成功時函式返回0,如果發生內部錯誤或者使用錯誤的引數,函式返回-1。
示例
#include <event2/event.h>/* Watch out! Including event_struct.h means that your code will not
* be binary-compatible with future versions of Libevent. */
#include <event2/event_struct.h>
#include <stdlib.h>struct event_pair {
evutil_socket_t fd;
structevent read_event;
structevent write_event;
};
void readcb(evutil_socket_t, short, void*);
void writecb(evutil_socket_t, short, void*);
struct event_pair *event_pair_new(struct event_base *base, evutil_socket_t fd)
{
struct event_pair *p = malloc(sizeof(struct event_pair));
if (!p) return NULL;
p->fd = fd;
event_assign(&p->read_event, base, fd, EV_READ|EV_PERSIST, readcb, p);
event_assign(&p->write_event, base, fd, EV_WRITE|EV_PERSIST, writecb, p);
return p;
}也可以用event_assign()初始化棧上分配的,或者靜態分配的事件。
警告
相關推薦
翻譯:libevent參考手冊第四章:與事件一起工作 (六) (轉)
libevent的基本操作單元是事件。每個事件代表一組條件的集合,這些條件包括:v 檔案描述符已經就緒,可以讀取或者寫入v 檔案描述符變為就緒狀態,可以讀取或者寫入(僅對於邊沿觸發IO)v 超時事件v 發生某訊號v 使用者觸發事件所有事件具有相似的生命週期。呼叫libevent函式設定事件並且關聯到event
翻譯:libevent參考手冊第九章:連線監聽器:接受TCP連線 (十一) (轉)
#include <event2/listener.h>#include <event2/bufferevent.h>#include <event2/buffer.h>#include <arpa/inet.h>#include <string.h>
翻譯:Libevent參考手冊第三章:與事件迴圈一起工作 (五) (轉)
預設情況下,event_base_loop()函式執行event_base直到其中沒有已經註冊的事件為止。執行迴圈的時候,函式重複地檢查是否有任何已經註冊的事件被觸發(比如說,讀事件的檔案描述符已經就緒,可以讀取了;或者超時事件的超時時間即將到達)。如果有事件被觸發,函式標記被觸發的事件為“啟用的”,並且執行
翻譯:libevent參考手冊第七章:Bufferevent:高階話題 (九) (轉)
bufferevent_filter_new()函式建立一個封裝現有的“底層”bufferevent的過濾bufferevent。所有通過底層bufferevent接收的資料在到達過濾bufferevent之前都會經過“輸入”過濾器的轉換;所有通過底層bufferevent傳送的資料在被髮送到底層buffer
翻譯:libevent參考手冊第五章:輔助型別和函式 (七) (轉)
這些巨集訪問和操作套接字錯誤程式碼。EVUTIL_SOCKET_ERROR()返回本執行緒最後一次套接字操作的全域性錯誤號,evutil_socket_geterror()則返回某特定套接字的錯誤號。(在類Unix系統中都是errno)EVUTIL_SET_SOCKET_ERROR()修改當前套接字錯誤號(與
翻譯:libevent參考手冊第八章:evbuffer:緩衝IO實用功能 (十) (轉)
{ /* Let's look at the first two chunks of buf, and write them to stderr. */int n, i; struct evbuffer_iovec v[2]; n = evbuffer_peek(buf, -1, NULL,
翻譯:libevent參考手冊第六章:bufferevent:概念和入門 (八) (轉)
bufferevent_setcb()函式修改bufferevent的一個或者多個回撥。readcb、writecb和eventcb函式將分別在已經讀取足夠的資料、已經寫入足夠的資料,或者發生錯誤時被呼叫。每個回撥函式的第一個引數都是發生了事件的bufferevent,最後一個引數都是呼叫buffereven
第四章 開始Unity Shader學習之旅(3)
行處理 由於 ctx 渲染 ima arc bubuko 這一 vpd 1. 程序員的煩惱:Debug
調試(debug),大概是所有程序員的噩夢。而不幸的是,對一個Shader進行調試更是噩夢中的噩夢。這也是造成Shader難寫的原因之一——如果發現得到的效果不對,我們就
翻譯:libevent參考手冊第二章:建立event_base (四) (轉)
呼叫event_config_avoid_method()可以通過名字讓libevent避免使用特定的可用後端。呼叫event_config_require_feature()讓libevent不使用不能提供所有指定特徵的後端。呼叫event_config_set_flag()讓libevent在建立even
翻譯:Libevent參考手冊第一章:設定libevent (三) (轉)
evthread_lock_callbacks結構體描述的鎖回撥函式及其能力。對於上述版本,lock_api_version欄位必須設定為EVTHREAD_LOCK_API_VERSION。必須設定supported_locktypes欄位為EVTHREAD_LOCKTYPE_*常量的組合以描述支援的鎖型別(
翻譯:Libevent參考手冊:前言 (二) (轉)
1 從一萬英尺外看LibeventLibevent是用於編寫高速可移植非阻塞IO應用的庫,其設計目標是:v 可移植性:使用libevent編寫的程式應該可以在libevent支援的所有平臺上工作。即使沒有好的方式進行非阻塞IO,libevent也應該支援一般的方式,讓程式可以在受限的環境中執行。v 速度:l
Netty In Action中文版 - 第四章:Transports(傳輸)
duplicate pipeline 客戶 下列表 bytes 線程安全 get 工具 jsb
本章內容
Transports(傳輸)NIO(non-blocking IO,New IO), OIO(Old IO,blocking IO), Local(本地),
讀構建之法 第四章:兩人合作
應用 結對編程 使用 一對一 測試 一個 比較 以及 領域 程序員寫的代碼最終是人在看,所以代碼規範很重要,原則是:簡明,易讀,無二義性。
不光是程序書寫的格式問題,還牽涉到程序設計、模塊之間的關系、設計模式等方方面面。
代碼復審的正確定義看代碼是否在代碼規範的框架內正確的
第四章:執行環境與作用域
logs 執行 引用傳遞 按值傳遞 ons fun col func clas
函數中對象的值是按值傳遞的 !(function () {
//對象的按值傳遞or按引用傳遞在函數中
function setName(obj) {
第四章:操作列表
clas str 3.3 轉換 一個 改變 導致 賦值 any 第四章:操作列表
4.1 遍歷整個列表
如果名單很長,將包含大量反復的代碼。另外,每當名單的長度發生變化時,都必須修改代碼。通過for
循環,可讓Python去處理這些問題
1)使用for循環來打印魔術師名
第四章:重構代碼[學習Android Studio漢化教程]
出現 introduce 編輯 rri 分享 成員 dialog fig ice 第四章
Refactoring Code
The solutions you develop in Android Studio will not always follow a straig
ES6標準入門 第四章:字符串的擴展
固定 缺陷 長度 需要 允許 實例對象 poi turn har 1、字符串的Unicode 表示法
JavaScript 允許采用 \uxxxx 表示一個字符,其中 xxxx 表示字符的碼點。
"\u0061" // "a"
ES5中的缺陷:
以上表示
Node入門教程(5)第四章:global 全局變量
-c 這不 .com clear 替換 http htm 取消 floating global - 全局變量
全局對象(global object),不要和 全局的對象( global objects )或稱標準內置對象混淆。這裏說的全局的對象是說在全局作用域裏的內的對象
第四章:活動圖
分享圖片 只有一個 什麽 分叉 img 面向 png 對象流 有一個
活動圖明確先做什麽,後坐什麽,什麽條件下做什麽。
活動圖也可以不面向對象,但流程圖一定面向過程。
一個活動圖一定有只有一個初始節點。終點為1~n。
如果有多個終點那麽可以有描述。
第四章:Spring AOP
edi 關註 aspectj 附加 aop 插入 out cert AC 4.1:面向切面編程 AOP是在運行期間將代碼切入到類的指定位置的編程思想。切面能幫助我們模塊化橫切關註點,實現橫切關註點的復用。Spring在運行期間將切面植入到指定的Bean中,實際是通過攔
翻譯:libevent參考手冊第四章:與事件一起工作 (六) (轉)
libevent的基本操作單元是事件。每個事件代表一組條件的集合,這些條件包括:v 檔案描述符已經就緒,可以讀取或者寫入v 檔案描述符變為就緒狀態,可以讀取或者寫入(僅對於邊沿觸發IO)v 超時事件v 發生某訊號v 使用者觸發事件所有事件具有相似的生命週期。呼叫libevent函式設定事件並且關聯到event
翻譯:libevent參考手冊第九章:連線監聽器:接受TCP連線 (十一) (轉)
#include <event2/listener.h>#include <event2/bufferevent.h>#include <event2/buffer.h>#include <arpa/inet.h>#include <string.h>
翻譯:Libevent參考手冊第三章:與事件迴圈一起工作 (五) (轉)
預設情況下,event_base_loop()函式執行event_base直到其中沒有已經註冊的事件為止。執行迴圈的時候,函式重複地檢查是否有任何已經註冊的事件被觸發(比如說,讀事件的檔案描述符已經就緒,可以讀取了;或者超時事件的超時時間即將到達)。如果有事件被觸發,函式標記被觸發的事件為“啟用的”,並且執行
翻譯:libevent參考手冊第七章:Bufferevent:高階話題 (九) (轉)
bufferevent_filter_new()函式建立一個封裝現有的“底層”bufferevent的過濾bufferevent。所有通過底層bufferevent接收的資料在到達過濾bufferevent之前都會經過“輸入”過濾器的轉換;所有通過底層bufferevent傳送的資料在被髮送到底層buffer
翻譯:libevent參考手冊第五章:輔助型別和函式 (七) (轉)
這些巨集訪問和操作套接字錯誤程式碼。EVUTIL_SOCKET_ERROR()返回本執行緒最後一次套接字操作的全域性錯誤號,evutil_socket_geterror()則返回某特定套接字的錯誤號。(在類Unix系統中都是errno)EVUTIL_SET_SOCKET_ERROR()修改當前套接字錯誤號(與
翻譯:libevent參考手冊第八章:evbuffer:緩衝IO實用功能 (十) (轉)
{ /* Let's look at the first two chunks of buf, and write them to stderr. */int n, i; struct evbuffer_iovec v[2]; n = evbuffer_peek(buf, -1, NULL,
翻譯:libevent參考手冊第六章:bufferevent:概念和入門 (八) (轉)
bufferevent_setcb()函式修改bufferevent的一個或者多個回撥。readcb、writecb和eventcb函式將分別在已經讀取足夠的資料、已經寫入足夠的資料,或者發生錯誤時被呼叫。每個回撥函式的第一個引數都是發生了事件的bufferevent,最後一個引數都是呼叫buffereven
第四章 開始Unity Shader學習之旅(3)
行處理 由於 ctx 渲染 ima arc bubuko 這一 vpd 1. 程序員的煩惱:Debug 調試(debug),大概是所有程序員的噩夢。而不幸的是,對一個Shader進行調試更是噩夢中的噩夢。這也是造成Shader難寫的原因之一——如果發現得到的效果不對,我們就
翻譯:libevent參考手冊第二章:建立event_base (四) (轉)
呼叫event_config_avoid_method()可以通過名字讓libevent避免使用特定的可用後端。呼叫event_config_require_feature()讓libevent不使用不能提供所有指定特徵的後端。呼叫event_config_set_flag()讓libevent在建立even
翻譯:Libevent參考手冊第一章:設定libevent (三) (轉)
evthread_lock_callbacks結構體描述的鎖回撥函式及其能力。對於上述版本,lock_api_version欄位必須設定為EVTHREAD_LOCK_API_VERSION。必須設定supported_locktypes欄位為EVTHREAD_LOCKTYPE_*常量的組合以描述支援的鎖型別(
翻譯:Libevent參考手冊:前言 (二) (轉)
1 從一萬英尺外看LibeventLibevent是用於編寫高速可移植非阻塞IO應用的庫,其設計目標是:v 可移植性:使用libevent編寫的程式應該可以在libevent支援的所有平臺上工作。即使沒有好的方式進行非阻塞IO,libevent也應該支援一般的方式,讓程式可以在受限的環境中執行。v 速度:l
Netty In Action中文版 - 第四章:Transports(傳輸)
duplicate pipeline 客戶 下列表 bytes 線程安全 get 工具 jsb 本章內容 Transports(傳輸)NIO(non-blocking IO,New IO), OIO(Old IO,blocking IO), Local(本地),
讀構建之法 第四章:兩人合作
應用 結對編程 使用 一對一 測試 一個 比較 以及 領域 程序員寫的代碼最終是人在看,所以代碼規範很重要,原則是:簡明,易讀,無二義性。 不光是程序書寫的格式問題,還牽涉到程序設計、模塊之間的關系、設計模式等方方面面。 代碼復審的正確定義看代碼是否在代碼規範的框架內正確的
第四章:執行環境與作用域
logs 執行 引用傳遞 按值傳遞 ons fun col func clas 函數中對象的值是按值傳遞的 !(function () { //對象的按值傳遞or按引用傳遞在函數中 function setName(obj) {
第四章:操作列表
clas str 3.3 轉換 一個 改變 導致 賦值 any 第四章:操作列表 4.1 遍歷整個列表 如果名單很長,將包含大量反復的代碼。另外,每當名單的長度發生變化時,都必須修改代碼。通過for 循環,可讓Python去處理這些問題 1)使用for循環來打印魔術師名
第四章:重構代碼[學習Android Studio漢化教程]
出現 introduce 編輯 rri 分享 成員 dialog fig ice 第四章 Refactoring Code The solutions you develop in Android Studio will not always follow a straig
ES6標準入門 第四章:字符串的擴展
固定 缺陷 長度 需要 允許 實例對象 poi turn har 1、字符串的Unicode 表示法 JavaScript 允許采用 \uxxxx 表示一個字符,其中 xxxx 表示字符的碼點。 "\u0061" // "a" ES5中的缺陷: 以上表示
Node入門教程(5)第四章:global 全局變量
-c 這不 .com clear 替換 http htm 取消 floating global - 全局變量 全局對象(global object),不要和 全局的對象( global objects )或稱標準內置對象混淆。這裏說的全局的對象是說在全局作用域裏的內的對象
第四章:活動圖
分享圖片 只有一個 什麽 分叉 img 面向 png 對象流 有一個 活動圖明確先做什麽,後坐什麽,什麽條件下做什麽。 活動圖也可以不面向對象,但流程圖一定面向過程。 一個活動圖一定有只有一個初始節點。終點為1~n。 如果有多個終點那麽可以有描述。
第四章:Spring AOP
edi 關註 aspectj 附加 aop 插入 out cert AC 4.1:面向切面編程 AOP是在運行期間將代碼切入到類的指定位置的編程思想。切面能幫助我們模塊化橫切關註點,實現橫切關註點的復用。Spring在運行期間將切面植入到指定的Bean中,實際是通過攔