libevent基础文件event-internal.h(struct event_base结构体)

时间:2023-01-25 00:15:16

该文件主要是定义了结构体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;
  1.      // 后台方法可以提供的特征  
  2.      // enum event_method_feature {  
  3.      // 边沿触发  
  4.      // EV_FEATURE_ET = 0x01,  
  5.      // 要求事后台方法在调度很多事件时大约为O(1)操作,select和poll无法提供这种特征,  
  6.      // 这两种方法具有N个事件时,可以提供O(N)操作  
  7.     // EV_FEATURE_O1 = 0x02,  
  8.   
  9.      // 后台方法可以处理各种文件描述符,而不仅仅是sockets  
  10.     // EV_FEATURE_FDS = 0x04,  
  11.     /** Require an event method that allows you to use EV_CLOSED to detect 
  12.      * connection close without the necessity of reading all the pending data. 
  13.      * 
  14.      * Methods that do support EV_CLOSED may not be able to provide support on 
  15.      * all kernel versions. 
  16.      **/  
  17.      // 要求后台方法允许使用EV_CLOSED特征检测链接是否中断,而不需要读取  
  18.      // 所有未决数据;但是不是所有内核都能提供这种特征  
  19.     // EV_FEATURE_EARLY_CLOSE = 0x08  
  20.     // };  
/** Length of the extra information we should record for each fd that has one or more active events. This information is recorded as part of the evmap entry for each fd, and passed as an argument to the add and del functions above. */ size_t fdinfo_len;};
 
#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;
  1.  // 指向后台特定的数据,是由evsel->init返回的句柄  
  2.  // 实际上是对实际后台方法所需数据的封装
/** List of changes to tell backend about at next dispatch. Only used * by the O(1) backends. */ struct event_changelist changelist; /** Function pointers used to describe the backend that this event_base * uses for signals */ const struct eventop *evsigsel; /** Data to implement the common signal handelr code. */ struct evsig_info sig; /** Number of virtual events */ int virtual_event_count; /** Number of total events added to this event_base */ int event_count; /** Number of total events active in this event_base */ int event_count_active; /** Set if we should terminate the loop once we're done processing * events. */ int event_gotterm; /** Set if we should terminate the loop immediately */ int event_break; /** Set if we should start a new instance of the loop immediately. */ int event_continue; /** The currently running priority of events */ int event_running_priority; /** Set if we're running the event_base_loop function, to prevent * reentrant invocation. */ int running_loop; /* Active event management. */ /** An array of nactivequeues queues for active events (ones that * have triggered, and whose callbacks need to be called). Low * priority numbers are more important, and stall higher ones. */ struct event_list *activequeues;   //activequeues[priority]是一个链表,链表中的每个结点都是优先级为priority的就绪事件event   /** The length of the activequeues array */ int nactivequeues;   //活跃链表的数目 ,不同优先级的event组织成不同的链表 /* common timeout logic */ /** An array of common_timeout_list* for all of the common timeout * values we know. */ struct common_timeout_list **common_timeout_queues; /** The number of entries used in common_timeout_queues */ int n_common_timeouts; /** The total size of common_timeout_queues. */ int n_common_timeouts_allocated; /** List of defered_cb that are active. We run these after the active * events. */ struct deferred_cb_queue defer_queue; /** Mapping from file descriptors to enabled (added) events */ struct event_io_map io; /** Mapping from signal numbers to enabled (added) events. */ struct event_signal_map sigmap; /** All events that have been enabled (added) in this event_base */ struct event_list eventqueue; /** Stored timeval; used to detect when time is running backwards. */ struct timeval event_tv; /** Priority queue of events with timeouts. */ struct min_heap timeheap;//最小根堆结构体 /** Stored timeval: used to avoid calling gettimeofday/clock_gettime * too often. */ struct timeval tv_cache;#if defined(_EVENT_HAVE_CLOCK_GETTIME) && defined(CLOCK_MONOTONIC) /** Difference between internal time (maybe from clock_gettime) and * gettimeofday. */ struct timeval tv_clock_diff; /** Second in which we last updated tv_clock_diff, in monotonic time. */ time_t last_updated_clock_diff;#endif#ifndef _EVENT_DISABLE_THREAD_SUPPORT /* threading support */ /** The thread currently running the event_loop for this base */ unsigned long th_owner_id; /** A lock to prevent conflicting accesses to this event_base */ void *th_base_lock; /** The event whose callback is executing right now */ struct event *current_event; /** A condition that gets signalled when we're done processing an * event with waiters on it. */ void *current_event_cond; /** Number of threads blocking on current_event_cond. */ int current_event_waiters;#endif /** Flags that this base was configured with */ enum event_base_config_flag flags;//event_base的配置选项,有以下可选:  enum event_base_config_flag { /** Do not allocate a lock for the event base, even if we have     locking set up. */ EVENT_BASE_FLAG_NOLOCK = 0x01, /** Do not check the EVENT_* environment variables when configuring     an event_base  */ EVENT_BASE_FLAG_IGNORE_ENV = 0x02, /** Windows only: enable the IOCP dispatcher at startup     If this flag is set then bufferevent_socket_new() and     evconn_listener_new() will use IOCP-backed implementations     instead of the usual select-based one on Windows. */ EVENT_BASE_FLAG_STARTUP_IOCP = 0x04, /** Instead of checking the current time every time the event loop is     ready to run timeout callbacks, check after each timeout callback. */ EVENT_BASE_FLAG_NO_CACHE_TIME = 0x08, /** If we are using the epoll backend, this flag says that it is     safe to use Libevent's internal change-list code to batch up     adds and deletes in order to try to do as few syscalls as     possible.  Setting this flag can make your code run faster, but     it may trigger a Linux bug: it is not safe to use this flag     if you have any fds cloned by dup() or its variants.  Doing so     will produce strange and hard-to-diagnose bugs.     This flag can also be activated by settnig the     EVENT_EPOLL_USE_CHANGELIST environment variable.     This flag has no effect if you wind up using a backend other than     epoll. */ EVENT_BASE_FLAG_EPOLL_USE_CHANGELIST = 0x10};上面这些配置选项的含义见英文。


/* 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;
};
现在无法解释event_base结构体的所有成员,只需记住几个重要成员:

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;