日本搞逼视频_黄色一级片免费在线观看_色99久久_性明星video另类hd_欧美77_综合在线视频

國(guó)內(nèi)最全I(xiàn)T社區(qū)平臺(tái) 聯(lián)系我們 | 收藏本站
阿里云優(yōu)惠2
您當(dāng)前位置:首頁(yè) > php框架 > 框架設(shè)計(jì) > libevent學(xué)習(xí)三

libevent學(xué)習(xí)三

來(lái)源:程序員人生   發(fā)布時(shí)間:2015-03-04 07:54:17 閱讀次數(shù):4324次

設(shè)定Libevent

Libevent有1些貫穿于全部程序的全局設(shè)定。它們影響著全部庫(kù)。你必須提早肯定這些設(shè)定,否則可能會(huì)造成不1致的狀態(tài)。


Libevent的日志消息

Libevent可以記錄內(nèi)部的毛病和經(jīng)過(guò)。固然編譯時(shí)增加了日志支持,它也會(huì)記錄調(diào)試信息。默許情況下,這些信息輸出到標(biāo)準(zhǔn)毛病。你可使用自己的調(diào)試方法去重寫它。

#define EVENT_LOG_DEBUG 0 #define EVENT_LOG_MSG 1 #define EVENT_LOG_WARN 2 #define EVENT_LOG_ERR 3 /* Deprecated; see note at the end of this section */ #define _EVENT_LOG_DEBUG EVENT_LOG_DEBUG #define _EVENT_LOG_MSG EVENT_LOG_MSG #define _EVENT_LOG_WARN EVENT_LOG_WARN #define _EVENT_LOG_ERR EVENT_LOG_ERR typedef void (*event_log_cb)(int severity, const char *msg); void event_set_log_callback(event_log_cb cb);
event_set_log_callback就是注冊(cè)日志輸出回調(diào)的方法。如果傳入NULL,它就會(huì)默許的輸出到標(biāo)準(zhǔn)毛病。重寫1個(gè)event_log_cb去定制自己的日志記錄。

例子:

#include <event2/event.h> #include <stdio.h> static void discard_cb(int severity, const char *msg) { /* This callback does nothing. */ } static FILE *logfile = NULL; static void write_to_file_cb(int severity, const char *msg) { const char *s; if (!logfile) return; switch (severity) { case _EVENT_LOG_DEBUG: s = "debug"; break; case _EVENT_LOG_MSG: s = "msg"; break; case _EVENT_LOG_WARN: s = "warn"; break; case _EVENT_LOG_ERR: s = "error"; break; default: s = "?"; break; /* never reached */ } fprintf(logfile, "[%s] %s ", s, msg); } /* Turn off all logging from Libevent. */ void suppress_logging(void) { event_set_log_callback(discard_cb); } /* Redirect all Libevent log messages to the C stdio file 'f'. */ void set_logfile(FILE *f) { logfile = f; event_set_log_callback(write_to_file_cb); }
注:如果你在event_log_cb內(nèi)部去調(diào)用Libevent函數(shù),極可能是不安全的。比如,如果你在1個(gè)log回調(diào)中使用bufferevents去向1個(gè)socket寫入1些正告信息,那你可能會(huì)遇到很奇異的bug。這1限制可能會(huì)在將來(lái)的版本中被解決。

默許情況下,debug日志是未被啟用的,不會(huì)被發(fā)送到日志回調(diào)中去。你可以手動(dòng)的去開(kāi)啟它。

接口

#define EVENT_DBG_NONE 0 #define EVENT_DBG_ALL 0xffffffffu void event_enable_debug_logging(ev_uint32_t which);

debug信息冗雜,而且在大多數(shù)情況下,沒(méi)有甚么用。EVENT_DBG_NONE默許不開(kāi)啟debug日志。EVENT_DBG_ALL會(huì)開(kāi)啟對(duì)debug日志的支持。


處理致命毛病

當(dāng)Libevent檢測(cè)到1個(gè)致命的內(nèi)部毛病(如1個(gè)被破壞的結(jié)構(gòu)),它的默許行動(dòng)是調(diào)用exit()或abort()去終止進(jìn)程。你可以提供1個(gè)自己的處理函數(shù),去覆蓋Libevent對(duì)這類致命毛病的處理。

接口

typedef void (*event_fatal_cb)(int err); void event_set_fatal_callback(event_fatal_cb cb);

提供你自己的event_fatal_cb版本,傳到event_set_fatal_callback()里面。當(dāng)有致命毛病產(chǎn)生時(shí),它就會(huì)調(diào)用你提供的方法了。在你的方法里不能再把控制權(quán)交給Libevent,1旦你的方法被調(diào)用,不要在里面再調(diào)用任何Libevent方法。


內(nèi)存管理
默許情況下,Libevent使用C語(yǔ)言庫(kù)提供的內(nèi)存相干方法(malloc,realloc,free)去從堆上分配內(nèi)存。當(dāng)你有更高效的內(nèi)存管理方案,或你想去查詢內(nèi)存泄漏的時(shí)候,Libevent允許你提供自己的malloc,realloc,free去管理內(nèi)存。

接口

void event_set_mem_functions(void *(*malloc_fn)(size_t sz), void *(*realloc_fn)(void *ptr, size_t sz), void (*free_fn)(void *ptr));
下面有個(gè)簡(jiǎn)單的例子,它統(tǒng)計(jì)被使用的內(nèi)存大小。在實(shí)際環(huán)境中,你可能需要加鎖去避免1些由于多線程釀成的毛病。
#include <event2/event.h> #include <sys/types.h> #include <stdlib.h> /* This union's purpose is to be as big as the largest of all the * types it contains. */ union alignment { size_t sz; void *ptr; double dbl; }; /* We need to make sure that everything we return is on the right alignment to hold anything, including a double. */ #define ALIGNMENT sizeof(union alignment) /* We need to do this cast-to-char* trick on our pointers to adjust them; doing arithmetic on a void* is not standard. */ #define OUTPTR(ptr) (((char*)ptr)+ALIGNMENT) #define INPTR(ptr) (((char*)ptr)-ALIGNMENT) static size_t total_allocated = 0; static void *replacement_malloc(size_t sz) { void *chunk = malloc(sz + ALIGNMENT); if (!chunk) return chunk; total_allocated += sz; *(size_t*)chunk = sz; return OUTPTR(chunk); } static void *replacement_realloc(void *ptr, size_t sz) { size_t old_size = 0; if (ptr) { ptr = INPTR(ptr); old_size = *(size_t*)ptr; } ptr = realloc(ptr, sz + ALIGNMENT); if (!ptr) return NULL; *(size_t*)ptr = sz; total_allocated = total_allocated - old_size + sz; return OUTPTR(ptr); } static void replacement_free(void *ptr) { ptr = INPTR(ptr); total_allocated -= *(size_t*)ptr; free(ptr); } void start_counting_bytes(void) { event_set_mem_functions(replacement_malloc, replacement_realloc, replacement_free); }
注:

1. 替換內(nèi)存管理方法會(huì)影響所有的內(nèi)存分配,重分配和釋放。所以必須確保在Libevent被使用前設(shè)置你提供的方法。否則你可能會(huì)用你提供的釋放函數(shù)去釋放從C庫(kù)分配來(lái)的內(nèi)存。
2. 你提供的malloc和realloc函數(shù)需要返回與C庫(kù)相同對(duì)齊的內(nèi)存塊。

3. 你的realloc方法需要注意處理realloc(NULL, sz)(也就是malloc(sz))。

4. 你的realloc方法需要注意處理realloc(ptr,0)(也就是free(ptr))。

5. 你的free方法不需要處理free(NULL)。注:沒(méi)必要的系統(tǒng)調(diào)用

6. 你的malloc不需要處理malloc(0)。注:沒(méi)必要的系統(tǒng)調(diào)用

7. 如果使用了多線程,需要注意線程安全。

8. 如果你提供了malloc和realloc,那末你同時(shí)也需要提供對(duì)應(yīng)版本的free函數(shù)。


鎖和線程

如果你有多線程的經(jīng)驗(yàn),那你可能知道,同1時(shí)間多個(gè)線程訪問(wèn)同1個(gè)數(shù)據(jù)多是不安全的。

在多線程環(huán)境下,Libevent的數(shù)據(jù)1般以3種方式存在。

1. 1些數(shù)據(jù)只用在單線程中:多個(gè)線程同時(shí)使用它,1定是不安全的。

2. 1些數(shù)據(jù)可以被選擇性的鎖定:在使用這些結(jié)構(gòu)時(shí),你可以告知它是不是用在多線程。

3. 1些數(shù)據(jù)總是被鎖定:運(yùn)行在多線程下,它們總是安全的。

要在Libevent中取得鎖,你必須提供相干鎖方法給Libevent。并且要確保在數(shù)據(jù)被多線程使用之前就必須提供好。

如果你想使用pthread庫(kù)或Windows本地線程庫(kù),這里提供了1些預(yù)定義的方法去讓Libevent正確安裝pthread或Windows方法。

接口

#ifdef WIN32 int evthread_use_windows_threads(void); #define EVTHREAD_USE_WINDOWS_THREADS_IMPLEMENTED #endif #ifdef _EVENT_HAVE_PTHREADS int evthread_use_pthreads(void); #define EVTHREAD_USE_PTHREADS_IMPLEMENTED #endif
這兩個(gè)方法產(chǎn)生毛病時(shí)返回⑴,成功時(shí)返回0。

如果你不想使用Libevent線程庫(kù),那你需要做1些額外的工作。你需要定義1些方法:

Locks

locking

unlocking

lock allocation

lock destruction

Conditions

condition variable creation

condition variable destruction

waiting on a condition variable

signaling/broadcasting to a condition variable

Threads

thread ID detection
然后你可以通過(guò)evthread_set_lock_callbacks和evthread_set_id_callback接口去向libevent注冊(cè)這些方法。

接口

#define EVTHREAD_WRITE 0x04 #define EVTHREAD_READ 0x08 #define EVTHREAD_TRY 0x10 #define EVTHREAD_LOCKTYPE_RECURSIVE 1 #define EVTHREAD_LOCKTYPE_READWRITE 2 #define EVTHREAD_LOCK_API_VERSION 1 struct evthread_lock_callbacks { int lock_api_version; unsigned supported_locktypes; void *(*alloc)(unsigned locktype); void (*free)(void *lock, unsigned locktype); int (*lock)(unsigned mode, void *lock); int (*unlock)(unsigned mode, void *lock); }; int evthread_set_lock_callbacks(const struct evthread_lock_callbacks *); void evthread_set_id_callback(unsigned long (*id_fn)(void)); struct evthread_condition_callbacks { int condition_api_version; void *(*alloc_condition)(unsigned condtype); void (*free_condition)(void *cond); int (*signal_condition)(void *cond, int broadcast); int (*wait_condition)(void *cond, void *lock, const struct timeval *timeout); }; int evthread_set_condition_callbacks( const struct evthread_condition_callbacks *);
evthread_lock_callbacks結(jié)構(gòu)體描寫了鎖的相干回調(diào)。對(duì)上邊描寫的版本,lock_api_versionbi必須被設(shè)置成EVTHREAD_LOCK_API_VERSION。supported_locktypes字段描寫的是鎖的類型,必須被設(shè)置為EVTHREAD_LOCKTYPE_*。alloc方法必須返回1個(gè)指定locktype的鎖。free方法必須釋放1個(gè)指定鎖的所有資源。lock方法必須實(shí)現(xiàn)去以指定模式取得某個(gè)鎖,成功返回0,失敗返回非0。unlock方法必須實(shí)現(xiàn)嘗試去解鎖,成功返回0,失敗返回非0。

公認(rèn)的鎖類型:

0:常規(guī)的,不需要可重入的鎖

EVTHREAD_LOCKTYPE_RECURSIVE:如果1個(gè)線程已持有了這個(gè)鎖,再次要求不會(huì)產(chǎn)生死鎖。1旦持有鎖的這個(gè)線程解鎖的次數(shù)和初始加鎖的次數(shù)相同,其他線程可以取得這個(gè)鎖。

EVTHREAD_LOCKTYPE_READWRITE: 這個(gè)鎖允許多個(gè)線程同時(shí)去讀,但是只允許1個(gè)線程去寫。

公認(rèn)的鎖模式:

EVTHREAD_READ:用于讀寫鎖,取得或釋放鎖用于讀

EVTHREAD_WRITE: 用于讀寫鎖,取得或釋放鎖用于寫

EVTHREAD_TRY:探查鎖是不是可以被獲得

id_fn參數(shù)是1個(gè)方法,它可以返回當(dāng)前正在運(yùn)行的線程的id,返回值是1個(gè)無(wú)符號(hào)長(zhǎng)整型類型。同1個(gè)線程返回相同的數(shù)。不同的線程1定返回不同的數(shù)。

evthread_condition_callbacks結(jié)構(gòu)描寫條件變量的相干回調(diào)。lock_api_version字段必須是EVTHREAD_CONDITION_API_VERSION。alloc_condition方法必須返回1個(gè)指向新條件變量的指針,它的參數(shù)是0。free_condition函數(shù)用來(lái)釋放被條件變量所持有資源。wait_condition函數(shù)有3個(gè)參數(shù):1.被alloc_condition分配的條件變量, 2. 被evthread_lock_callbacks.alloc分配的鎖變量,3. 可選的超時(shí)時(shí)間。函數(shù)被調(diào)用的時(shí)候,它1定持有著鎖;然后釋放鎖,1直等待到接收了條件變量的信號(hào)或等待timeout時(shí)間溢出。wait_condition產(chǎn)生毛病返回⑴,被條件變量信號(hào)喚醒返回0,超時(shí)返回1。在它返回之前,必須確保它再次持有鎖。最后,如果broadcast為false,signal_function會(huì)喚醒1個(gè)等待在此條件變量上的線程,如果broadcast為true,喚醒所有等待在此條件變量上的線程。

調(diào)試鎖功能

Libevent提供了“調(diào)試鎖”的特性。調(diào)試鎖是用來(lái)捕獲鎖調(diào)用出現(xiàn)的1些特定毛病:

1. 解鎖1個(gè)當(dāng)前線程未持有的鎖。

2. 重鎖1個(gè)非重入鎖。

如果產(chǎn)生了以上的毛病,Libevent會(huì)直接退出。

接口

void evthread_enable_lock_debugging(void); #define evthread_enable_lock_debuging() evthread_enable_lock_debugging()
注:這個(gè)方法必須在鎖被創(chuàng)建或使用前就調(diào)用。可以在設(shè)置線程功能后就調(diào)用它。

調(diào)試事件功能

對(duì)事件的1些常規(guī)毛病,Libevent是可以檢測(cè)并且報(bào)告給你的。他們包括:

1. 使用1個(gè)未初始化的事件結(jié)構(gòu)體

2. 2次初始化1個(gè)事件的結(jié)構(gòu)體
追蹤事件是不是被初始化,需要額外的內(nèi)存和CPU,所以僅需在調(diào)試階段的時(shí)候才需要去開(kāi)啟它。

接口

void event_enable_debug_mode(void);
這個(gè)方法必須在event_base創(chuàng)建前就被調(diào)用。

在使用調(diào)試模式時(shí),如果你的程序使用了大量由event_assign()[而不是event_new()]創(chuàng)建的event,那可能會(huì)造成內(nèi)存溢出。這是由于當(dāng)使用event_assign()去創(chuàng)建1個(gè)event時(shí),它多是在棧上的1個(gè)對(duì)象,Libevent沒(méi)辦法辨別這個(gè)event甚么時(shí)候不再被使用。(而當(dāng)使用event_new()創(chuàng)建event的時(shí)候,它是1個(gè)堆內(nèi)存上的數(shù)據(jù),Libevent是可以通過(guò)調(diào)用event_free()去知道這個(gè)event是無(wú)效的)。固然如果你想在調(diào)試的時(shí)候不出現(xiàn)內(nèi)存溢出,你可以顯示的告知Libevent,這些events不再被當(dāng)作是分配的。

接口

void event_debug_unassign(struct event *ev);
當(dāng)調(diào)試模式被制止時(shí),對(duì)event_debug_unassign()的調(diào)用是沒(méi)影響的。

例子:

#include <event2/event.h> #include <event2/event_struct.h> #include <stdlib.h> void cb(evutil_socket_t fd, short what, void *ptr) { /* We pass 'NULL' as the callback pointer for the heap allocated * event, and we pass the event itself as the callback pointer * for the stack-allocated event. */ struct event *ev = ptr; if (ev) event_debug_unassign(ev); } /* Here's a simple mainloop that waits until fd1 and fd2 are both * ready to read. */ void mainloop(evutil_socket_t fd1, evutil_socket_t fd2, int debug_mode) { struct event_base *base; struct event event_on_stack, *event_on_heap; if (debug_mode) event_enable_debug_mode(); base = event_base_new(); event_on_heap = event_new(base, fd1, EV_READ, cb, NULL); event_assign(&event_on_stack, base, fd2, EV_READ, cb, &event_on_stack); event_add(event_on_heap, NULL); event_add(&event_on_stack, NULL); event_base_dispatch(base); event_free(event_on_heap); event_base_free(base); }
調(diào)試的詳細(xì)情況可以通過(guò)在編譯時(shí)添加'-DUSE_DEBUG'參數(shù)來(lái)啟用。如果這個(gè)標(biāo)志被啟用,那末使用Libevent程序的服務(wù)器端會(huì)輸出1個(gè)非常冗雜的日志。其中包括:

1. event 增加

2. event 刪除

3. 平臺(tái)相干的event通知信息

這個(gè)功能不能通過(guò)API去啟用或禁用,所有只能被用在開(kāi)發(fā)階段。

釋放全局Libevent數(shù)據(jù)
當(dāng)你釋放了所有Libevent的數(shù)據(jù),可1些全局的數(shù)據(jù)仍然被留下來(lái)。正常情況下是沒(méi)問(wèn)題的,由于1旦程序退出,內(nèi)核會(huì)自動(dòng)釋放進(jìn)程的所有內(nèi)存。但是如果你使用1些內(nèi)存泄漏的檢測(cè)工具,來(lái)檢查內(nèi)存泄漏的情況時(shí),這些全局?jǐn)?shù)據(jù)會(huì)被當(dāng)作未釋放的內(nèi)存被檢測(cè)出來(lái),影響你的調(diào)試。你可以通過(guò)調(diào)用以下接口:
接口:

void libevent_global_shutdown(void);
這個(gè)方法不會(huì)釋放那些通過(guò)Libevent方法返回給你的數(shù)據(jù)。你需要自己手動(dòng)的去釋放它們。

這個(gè)方法應(yīng)當(dāng)在最后調(diào)用,就是調(diào)用它后,不要再使用任何Libevent的方法。

生活不易,碼農(nóng)辛苦
如果您覺(jué)得本網(wǎng)站對(duì)您的學(xué)習(xí)有所幫助,可以手機(jī)掃描二維碼進(jìn)行捐贈(zèng)
程序員人生
------分隔線----------------------------
分享到:
------分隔線----------------------------
關(guān)閉
程序員人生
主站蜘蛛池模板: 国产福利影院 | 九九在线免费视频 | 欧美a在线| 欧美日韩在线视频一区二区 | 亚洲女人天堂成人av在线 | 亚洲第一在线视频 | 国产一区精品视频 | 国产欧美日韩视频 | 亚洲九九九九 | 国产综合网站 | 欧美不卡一区二区三区 | 91精品网 | 视频精品一区二区三区 | 三级福利| 色网影院 | 99国产视频 | 色综合一区二区三区 | 中文字幕av在线播放 | 亚洲成人一区二区 | 久久久久久国产免费 | 日韩在线视频一区二区三区 | 亚洲精品在线播放 | 国产传媒在线视频 | 精品一区二区三区在线播放 | 国产精品久久久久久久 | 久久精品国产亚洲一区二区三区 | 97在线精品| 欧美色图在线观看 | 另类激情亚洲 | 久久免费播放视频 | 欧美精品不卡 | 精品国产一区二区三区四区四 | 男人天堂国产 | 91精品久久久久 | 精品国产一区二区三区麻豆小说 | 夜夜骑视频 | 国产在线v | 国产精品15p | 99免费精品 | 狠狠狠狠干 | 国产日韩欧美 |