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会乱掉()
 
相关文章
相关标签/搜索