转载请注明出处: http://blog.csdn.net/luotuo44/article/details/38556059
一般来说,是主线程执行event_base_dispatch函数。本文也是如此,如无特别说明,event_base_dispatch函数是由主线程执行的。
notify的理由:
本文要说明的问题是,当主线程在执行event_base_dispatch进入多路IO复用函数时,会处于休眠状态,休眠前解锁。此时,其他线程可能想往event_base添加一个event,这个event可能是一般的IO event也可能是超时event。无论哪个,都需要及时告知主线程:有新的event要加进来。要实现这种功能就需要Libevent提供一种机制来提供唤醒主线程。
工作原理:
Libevent提供的唤醒主线程机制也是挺简单的,其原理和《信号event的处理》一文中提到的方法是一样的。提供一个内部的IO event,专门用于唤醒主线程。当其他线程有event要add进来时,就往这个内部的IO event写入一个字节。此时,主线程在dispatch时,就能检测到可读,也就醒来了。这就完成了通知。这过程和Libevent处理信号event是一样的。
相关结构体:
下面看一下Libevent的实现代码。同信号处理一样,先来看一下event_base提供了什么成员。
struct event_base {
…
//event_base是否处于通知的未决状态。即次线程已经通知了,但主线程还没处理这个通知
int is_notify_pending;
evutil_socket_t th_notify_fd[2]; //通信管道
struct event th_notify;//用于监听th_notify_fd的读端
//有两个可供选择的通知函数,指向其中一个通知函数
int (*th_notify_fn)(struct event_base *base);
};
创建通知event并将之加入到event_base:
现在看Libevent怎么创建通信通道,以及怎么和event相关联。在event_base_new_with_config(event_base_new会调用该函数)里面会调用evthread_make_base_notifiable函数,使得libevent变成可通知的。只有在已经支持多线程的情况下才会调用evthread_make_base_notifiable函数的。//event.c文件
int
evthread_make_base_notifiable(struct event_base *base)
{
//默认event回调函数和默认的通知函数
void (*cb)(evutil_socket_t, short, void *) = evthread_notify_drain_default;
int (*notify)(struct event_base *) = evthread_notify_base_default;
/* XXXX grab t