该文件主要是定义了结构体strcut event_base,该结构体里面有许多成员是结构体,也在本文件定义,比如struct eventop,struct event_signal_map ,struct common_timeout_list,struct event_changelist,先介绍这些结构体,再介绍event_base。
/** Structure to define the backend of a given event_base. */
struct eventop {
/** The name of this backend. */
const char *name;// 后台方法名字,即epoll,select,poll等
/** Function to set up an event_base to use this backend. It should
* create a new structure holding whatever information is needed to
* run the backend, and return it. The returned pointer will get
* stored by event_init into the event_base.evbase field. On failure,
* this function should return NULL. */
// 建立一个event_base以使用当前后台方法,他应该创建一个新的结构体,
// 保存后台方法运行所需的信息,然后返回这个结构体。返回的指针将保存在event_base.evbase中;如果失败,
// 将返回NULL
void *(*init)(struct event_base *);
/** Enable reading/writing on a given fd or signal. 'events' will be
* the events that we're trying to enable: one or more of EV_READ,
* EV_WRITE, EV_SIGNAL, and EV_ET. 'old' will be those events that
* were enabled on this fd previously. 'fdinfo' will be a structure
* associated with the fd by the evmap; its size is defined by the
* fdinfo field below. It will be set to 0 the first time the fd is
* added. The function should return 0 on success and -1 on error.
*/
// 使给定的文件描述符或者信号变得可读或者可写。’events’将是我们尝试添加的
// 事件类型:EV_READ,EV_WRITE,EV_SIGNAL,EV_ET的组合。’old’是该fd
// 先前添加的事件类型;’fdinfo’将是fd在evmap中的辅助结构体信息,它的大小由下面的
// fdinfo_len给出。fd第一次添加时fdinfo将设置为0.成功则返回0,失败则返回-1
int (*add)(struct event_base *, evutil_socket_t fd, short old, short events, void *fdinfo);
/** As "add", except 'events' contains the events we mean to disable. */
int (*del)(struct event_base *, evutil_socket_t fd, short old, short events, void *fdinfo);
/** Function to implement the core of an event loop. It must see which
added events are ready, and cause event_active to be called for each
active event (usually via event_io_active or such). It should
return 0 on success and -1 on error.
*/
//event_loop实现的核心代码。他必须察觉哪些添加的事件已经准备好,然后
int (*dispatch)(struct event_base *, struct timeval *);
/** Function to clean up and free our data from the event_base. */ void (*dealloc)(struct event_base *); /** Flag: set if we need to reinitialize the event base after we fork. */ int need_reinit; /** Bit-array of supported event_method_features that this backend can * provide. */ enum event_method_feature features;
- // 后台方法可以提供的特征
- // enum event_method_feature {
- // 边沿触发
- // EV_FEATURE_ET = 0x01,
- // 要求事后台方法在调度很多事件时大约为O(1)操作,select和poll无法提供这种特征,
- // 这两种方法具有N个事件时,可以提供O(N)操作
- // EV_FEATURE_O1 = 0x02,
- // 后台方法可以处理各种文件描述符,而不仅仅是sockets
- // EV_FEATURE_FDS = 0x04,
- /** Require an event method that allows you to use EV_CLOSED to detect
- * connection close without the necessity of reading all the pending data.
- *
- * Methods that do support EV_CLOSED may not be able to provide support on
- * all kernel versions.
- **/
- // 要求后台方法允许使用EV_CLOSED特征检测链接是否中断,而不需要读取
- // 所有未决数据;但是不是所有内核都能提供这种特征
- // EV_FEATURE_EARLY_CLOSE = 0x08
- // };
#define event_io_map event_signal_map/* Used to map signal numbers to a list of events. If EVMAP_USE_HT is not defined, this structure is also used as event_io_map, which maps fds to a list of events.libevent使用event_signal_map结构来管理signal类型的event
entries是一个二级指针,理解为一个指针数组吧,nentries指定了数组的大小,
entries[0] ``` entires[nentires-1],每个元素都是一个evmap_signal类型的指针,下标代表信号的ID该结构体如下:
struct evmap_signal {
struct event_list events;
};每个evmap_signal都包含一个event_list链表,这样所有监视相同signal的事件都会被存储在一个链表中,关于这部分的实现以后分析。
*/
struct event_signal_map {
/* An array of evmap_io * or of evmap_signal *; empty entries are
* set to NULL. */
void **entries;
/* The number of entries available in entries */
int nentries;
};
/* A list of events waiting on a given 'common' timeout value. Ordinarily,
* events waiting for a timeout wait on a minheap. Sometimes, however, a
* queue can be faster.
**/
struct common_timeout_list {
/* List of events currently waiting in the queue. */
struct event_list events;
/* 'magic' timeval used to indicate the duration of events in this
* queue. */
struct timeval duration;
/* Event that triggers whenever one of the events in the queue is
* ready to activate */
struct event timeout_event;
/* The event_base that this timeout list is part of */
struct event_base *base;
};
/* List of 'changes' since the last call to eventop.dispatch. Only maintained
* if the backend is using changesets. */
struct event_changelist {
struct event_change *changes;
int n_changes;
int changes_size;
};
struct event_base {
/** Function pointers and other data to describe this event_base's
* backend. */
const struct eventop *evsel;//指向event_base锁使用的后台方法
/** Pointer to backend-specific data. */
void *evbase;
- // 指向后台特定的数据,是由evsel->init返回的句柄
- // 实际上是对实际后台方法所需数据的封装
现在无法解释event_base结构体的所有成员,只需记住几个重要成员:
/* Notify main thread to wake up break, etc. */
/** True if the base already has a pending notify, and we don't need
* to add any more. */
int is_notify_pending;
/** A socketpair used by some th_notify functions to wake up the main
* thread. */
evutil_socket_t th_notify_fd[2];
/** An event used by some th_notify functions to wake up the main
* thread. */
struct event th_notify;
/** A function used to wake up the main thread from another thread. */
int (*th_notify_fn)(struct event_base *base);
};
struct event_config_entry {
TAILQ_ENTRY(event_config_entry) next;
const char *avoid_method;
};
const struct eventop *evsel;后台的实现方法
void *evbase;//后台方法的特定数据
int event_count;//该event_base的event数目
int event_count_active;//活跃的event数目
struct event_list *activequeues;//结构体数组
int nactivequeues;//activequeues数组的长度
struct min_heap timeheap;//一个最小根堆
struct event_list eventqueue;//event链表,存储所有的event
struct event_io_map io;//这两个结构体是实现event到io描述符或者信号的映射
struct event_signal_map sigmap;