Libevent 的多線程操做

原由是event_base 跨線程add/remove event 致使崩潰或者死循環。html

據查:libvent 1.4.x是非線程安全的,要跨線程執行event_add,會有問題。
所以傳統作法是經過pipe來通知宿主線程執行event_add操做。
libevent 2.0.x經過線程鎖作到了線程安全,能夠跨線程執行event_add。web

須要在建立event_base以前調用evthread_use_pthreads(),須要添加event_pthread 庫,函數定義在event/thread.h安全

// 原理參照自 http://blog.chinaunix.net/uid-17260303-id-3342299.html多線程

libevent關於多線程的使用須要在全部的初始化以前加evthread_use_pthreads()函數的緣由:
evthread_use_pthreads()定義在evthread_pthread.c裏面。在這個函數裏,初始化了一個evthread_lock_callbacks對象 cbs,而後調用evthread_set_lock_callbacks(&cbs);來的對cbs這個evthread_lock_callbacks對象作操做。evthread_set_lock_callbacks定義在evthread.c裏面。在這個函數裏,其實就是將cbs的值賦值給了全局變量_evthread_lock_fns。
在定義了_EVENT_DISABLE_THREAD_SUPPORT的狀況下
在add_event函數裏面,libevent調用了EVBASE_ACQUIRE_LOCK這個宏。這個宏定義在evthread-internal.h, 同時EVBASE_ACQUIRE_LOCK這個宏又調用了EVLOCK_LOCK,EVLOCK_LOCK又調用了全局變量_evthread_lock_fns的lock成員。這個_evthread_lock_fns就是以前說過的那個。因此其實就是調用了evthread_use_pthreads()函數設置的_evthread_lock_fns這個結構體的lock成員。而這個lock成員函數,根據evthread_use_pthreads()函數裏面設置的值,就是evthread_posix_lock函數,其中參數mode是0,參數_lock是base.th_base_lock。因此其實就是pthread_mutex_lock(base.th_base_lock)
在沒有定義_EVENT_DISABLE_THREAD_SUPPORT的狀況下
在add_event函數裏面,libevent調用了EVBASE_ACQUIRE_LOCK這個宏。這個宏定義在evthread-internal.h, 同時EVBASE_ACQUIRE_LOCK這個宏又調用了EVLOCK_LOCK,EVLOCK_LOCK又調用了函數_evthreadimpl_lock_lock(),參數mode是0,參數lock是base.th_base_lock。_evthreadimpl_lock_lock定義在evthread.c裏面。在_evthreadimpl_lock_lock函數裏面,會先判斷全局變量_evthread_lock_fns的lock存不存在。若是存在就調用_evthread_lock_fns的lock成員,至關於就是調用evthread_posix_lock函數了,就和定義了_EVENT_DISABLE_THREAD_SUPPORT的狀況同樣了。若是不存在就什麼都不幹,返回0。
由於個人環境裏面是沒有定義_EVENT_DISABLE_THREAD_SUPPORT的,因此若是不在開始的時候調用evthread_use_pthreads(),那麼全局變量_evthread_lock_fns就沒有被賦值,他的lock成員天然也就是NULL了。因此,EVBASE_ACQUIRE_LOCK宏其實什麼都沒幹,也就沒有加鎖,因此在多個線程裏面add_event會亂掉()
 
相關文章
相關標籤/搜索