目录
event
event_base
eventop
evcb_closure
event_callback
event_changelist
evsig_info
event_io_map
event_iocp_port
struct event {
// 事件回调 下文有注解
struct event_callback ev_evcallback;
//超时管理
union {
TAILQ_ENTRY(event) ev_next_with_common_timeout; // 事件队列
int min_heap_idx; // 事件在最小堆中的index
} ev_timeout_pos;
evutil_socket_t ev_fd; // socket 描述符
// 下文有注解
struct event_base *ev_base;
union {
// 使用独写事件
struct {
LIST_ENTRY (event) ev_io_next; // 事件链表 ,链接下一个事件
struct timeval ev_timeout; // 事件超时时间
} ev_io;
// 使用信号事件
struct {
LIST_ENTRY (event) ev_signal_next; // 事件链表 ,链接下一个事件
short ev_ncalls; // 回调数量
short *ev_pncalls; // 允许在回调中删除
} ev_signal;
} ev_;
// ev_events :
// EV_TIMEOUT 0x01 超时
// EV_READ 0x02 读
// EV_WRITE 0x04 写
// EV_SIGNAL 0x08 信号
// EV_PERSIST 0x10 持久事件 激活时不会自动删除,超时激活 超时重置为0
// EV_ET 0x20 边缘触发
// EV_FINALIZE 0x40 终止事件 event_del不会阻塞 ,需要使用 event_finalize 或
// event_free_finalize 来保证线程安全
// EV_CLOSED 0x80 连接关闭
short ev_events;
short ev_res; // 结果传递给事件回调
struct timeval ev_timeout; // 事件超时时间
};
struct event_base {
// 函数指针和其他数据来描述event_base的后端,也就是所谓的epoll iocp kqueue等
// 下文有注解样例
const struct eventop *evsel;
// 指向后端特定数据指针,上面 evsel Init初始化后返回值赋值给 evbase
void *evbase;
// 事件变化列表 ,有变化的事件会进行下一次分发 下文有注解
struct event_changelist changelist;
// 用函数指针来描述event_base的后端,用于信号
const struct eventop *evsigsel;
// 处理通用信号数据 下文有注解
struct evsig_info sig;
// 虚拟事件数量
int virtual_event_count;
// 最大活跃虚拟事件数量
int virtual_event_count_max;
// 添加到此event_base的事件的数量
int event_count;
// 添加到此event_base的事件的最大数量
int event_count_max;
// 事件活跃数量
int event_count_active;
// 事件最大活跃数量
int event_count_active_max;
// 设置是否在完成事件处理后终止循环
int event_gotterm;
// 设置是否应该立即终止循环
int event_break;
// 设置是否立即开始一个新的循环实例
int event_continue;
// 当前正在运行事件的优先级
int event_running_priority;
// 设置我们是否正在运行 event_base_loop 函数,以防止可重入调用
int running_loop;
// 设置在循环,防饥饿标志
int n_deferreds_queued;
//此处用双向队列管理激活的事件
// TAILQ_HEAD(evcallback_list, event_callback);
// #define TAILQ_HEAD(name, type) \
// struct name { \
// struct type *tqh_first; /* first element */ \
// struct type **tqh_last; /* addr of last next element */ \
// }
struct evcallback_list *activequeues;
// activequeues 链表长度
int nactivequeues;
// 下次激活时候处理 的 evcallback_list
struct evcallback_list active_later_queue;
// 公共超时链表
struct common_timeout_list **common_timeout_queues;
// common_timeout_queues 队列中的数量
int n_common_timeouts;
// common_timeout_queues 的size
int n_common_timeouts_allocated;
// 事件读写Map看下文有注解
struct event_io_map io;
// 信号到事件的映射
struct event_signal_map sigmap;
// 超时事件的优先队列
struct min_heap timeheap;
// 存储时间值,用于避免调用 gettimeofday/clock_gettime
struct timeval tv_cache;
// 系统启动以后流逝的时间
struct evutil_monotonic_timer monotonic_timer;
/** Difference between internal time (maybe from clock_gettime) and
* gettimeofday. */
struct timeval tv_clock_diff; // 时钟差异
// 上次更新tv_clock_diff的第二个时间
time_t last_updated_clock_diff;
#ifndef EVENT__DISABLE_THREAD_SUPPORT // 多线程管理
// 当前loop的线程ID
unsigned long th_owner_id;
// event_base 的锁,针对多线程,处理同步
void *th_base_lock;
// 条件变量,处理同步
void *current_event_cond;
阻塞在 current_event_cond 上的线程数量
int current_event_waiters;
#endif
// 正在执行回调的事件 下文有详细注解
struct event_callback *current_event;
#ifdef _WIN32
// IOCP 支持结构 下文有详细注解
struct event_iocp_port *iocp;
#endif
// 配置标志
/*
enum event_base_config_flag
{
// 不给这个event_base分配锁,即使有锁设定,可以省去加锁解锁消耗,但多线程下不安全
EVENT_BASE_FLAG_NOLOCK = 0x01,
// 不检查 EVENT_* 环境变量
EVENT_BASE_FLAG_IGNORE_ENV = 0x02,
// 仅对windows有效,启用Libevent时 bufferevent_socket_new() 和
evconn_listener_new() 将使用 IOCP 支持的实现,而不是在需要时才使用
EVENT_BASE_FLAG_STARTUP_IOCP = 0x04,
// 在每个超时回调后检测当前时间,而不是在超时回调前检测
EVENT_BASE_FLAG_NO_CACHE_TIME = 0x08,
// 如果使用EPOLL后端,使用change-list 是安全的,可以让代码运行更快
EVENT_BASE_FLAG_EPOLL_USE_CHANGELIST = 0x10,
// 使用效率低但更精准的计时器
EVENT_BASE_FLAG_PRECISE_TIMER = 0x20
};
*/
enum event_base_config_flag flags;
// 事件循环的最大事件
struct timeval max_dispatch_time;
int max_dispatch_callbacks; // 事件循环中可以处理最大的回调数量
int limit_callbacks_after_prio; // 回调函数优先级限制
int is_notify_pending; //通知主线程唤醒休息的线程
// 一个socketpair, 使用 th_notify_fn 函数唤醒主线程
evutil_socket_t th_notify_fd[2];
// 事件触发的时候 使用 th_notify_fn 函数唤醒主线程
struct event th_notify;
// 子线程唤醒主线程的回调函数
int (*th_notify_fn)(struct event_base *base);
// 随机数种子 受 th_base_lock 保护
struct evutil_weakrand_state weakrand_seed;
// 尚未触发的通过event_once注册的事件链表
LIST_HEAD(once_event_list, event_once) once_events;
};
struct eventop {
/** 后端的名字. */
const char *name;
//初始化一个event_base 来使用这个后端函数,运行得到返回值会赋给event_base.evbase
void *(*init)(struct event_base *);
// 激活一个给定的文件描述符或者信号上启动读/写,例 EV_READ,EV_WRITE,EV_SIGNAL, EV_ET
int (*add)(struct event_base *, evutil_socket_t fd,
short old, short events, void *fdinfo);
// del和add相反
int (*del)(struct event_base *, evutil_socket_t fd,
short old, short events, void *fdinfo);
// 事件循环核心函数 事件就绪时为每个事件调用event_active
int (*dispatch)(struct event_base *, struct timeval *);
// 清除和释放 event_base
void (*dealloc)(struct event_base *);
// 在fork后是否需要重新初始化event_base
int need_reinit;
// 用于描述 event_base 提供了哪些功能的标志
event_config_require_features() 告诉 Libevent 仅在您的
event_base 实现了一个给定的特性
// event_base_get_features() 以查看哪些功能可用
// event_config_require_features()输入应用程序要求的必需 event 方法功能
// EV_FEATURE_ET = 0x01, 边缘触发
// EV_FEATURE_O1 = 0x02, O(1)事件触发 不轮询 epoll,kqueue
// EV_FEATURE_FDS = 0x04, 可以处理包括sockets在内的各种文件描述符
// EV_FEATURE_EARLY_CLOSE = 0x08, 可以使用EV_CLOSED检测连接关闭,不需读完所有挂起数据
enum event_method_feature features;
// 文件描述符记录的信息长度,会作为参数传给上面的add和del
size_t fdinfo_len;
};
/* 例
const struct eventop epollops =
{
"epoll",
epoll_init,
epoll_nochangelist_add,
epoll_nochangelist_del,
epoll_dispatch,
epoll_dealloc,
1, // need reinit
EV_FEATURE_ET|EV_FEATURE_O1|EV_FEATURE_EARLY_CLOSE,
0
};
*/
// 一个常规事件 使用 evcb_callback 回调
#define EV_CLOSURE_EVENT 0
// 一个信号事件 使用 evcb_callback 回调
#define EV_CLOSURE_EVENT_SIGNAL 1
// 一个持久的非信号事件 使用 evcb_callback 回调
#define EV_CLOSURE_EVENT_PERSIST 2
// 一个简单的回调 使用 evcb_selfcb 回调
#define EV_CLOSURE_CB_SELF 3
// 最终回调 使用 evcb_cbfinalize 回调
#define EV_CLOSURE_CB_FINALIZE 4
// 一个终止事件 使用 evcb_evfinalize 回调
#define EV_CLOSURE_EVENT_FINALIZE 5
// 结束后应该被释放的事件 使用 evcb_evfinalize 回调
#define EV_CLOSURE_EVENT_FINALIZE_FREE 6
struct event_callback {
TAILQ_ENTRY(event_callback) evcb_active_next; // 下一个event_callback实例的指针
/* evcb_flags
#define EVLIST_TIMEOUT 0x01 // 超时,事件在time min_heap堆中
#define EVLIST_INSERTED 0x02 // 事件在已注册事件链表中
#define EVLIST_SIGNAL 0x04 // 信号,目前暂未使用
#define EVLIST_ACTIVE 0x08 // 事件在激活链表中
#define EVLIST_INTERNAL 0x10 // 内部使用标记
#define EVLIST_ACTIVE_LATER 0x20 // 延迟激活,事件在下一次激活链表中
#define EVLIST_FINALIZING 0x40 // 事件已终止
#define EVLIST_INIT 0x80 // 事件初始化完成
#define EVLIST_ALL 0xff // 判断合法性
*/
short evcb_flags; // 选择回调类型
ev_uint8_t evcb_pri; /* 较小的数字具有更高的优先级 */
ev_uint8_t evcb_closure;
/* 允许采用不同类型的事件回调 */
union {
void (*evcb_callback)(evutil_socket_t, short, void *);
void (*evcb_selfcb)(struct event_callback *, void *);
void (*evcb_evfinalize)(struct event *, void *);
void (*evcb_cbfinalize)(struct event_callback *, void *);
} evcb_cb_union;
// 回调参数
void *evcb_arg;
};
struct event_changelist
{
struct event_change *changes;
int n_changes;
int changes_size;
};
struct event_change
{
// 改变事件的文件描述符或信号
evutil_socket_t fd;
// 更改前的旧事件
short old_events;
// 更改标志 unsigned char
ev_uint8_t read_change;
ev_uint8_t write_change;
ev_uint8_t close_change;
};
struct evsig_info {
/* Event watching ev_signal_pair[1] */
struct event ev_signal;
/* Socketpair 从信号处理handler出发送通知*/
evutil_socket_t ev_signal_pair[2];
// 如果添加了 ev_signal 事件则为真
int ev_signal_added;
// 信号计数
int ev_n_signals_added;
#ifdef EVENT__HAVE_SIGACTION
struct sigaction **sh_old; // 指针数组,存放信号处理函数
#else
ev_sighandler_t **sh_old; // 指针数组,存放信号处理函数
#endif
// 数组指针size
int sh_old_max;
};
#ifdef _WIN32 // 如果在win32中
#define EVMAP_USE_HT // 则定义 EVMAP_USE_HT
#endif
/* #define HT_CACHE_HASH_VALS */
#ifdef EVMAP_USE_HT
#define HT_NO_CACHE_HASH_VALUES
#include "ht-internal.h"
struct event_map_entry;
HT_HEAD(event_io_map, event_map_entry); // 如果在windows环节下,event_io_map会使用哈希结构
#else
#define event_io_map event_signal_map // 否则当成 event_signal_map 来使用
#endif
struct event_signal_map
{
void **entries; // 二级指针,evmap_signal* 数组
int nentries; // evmap_signal* 个数
};
#ifdef HT_NO_CACHE_HASH_VALUES
#define HT_ENTRY(type) \
struct { \
struct type *hte_next; \
}
#else
#define HT_ENTRY(type) \
struct { \
struct type *hte_next; \
unsigned hte_hash; \
}
#endif
#define HT_HEAD(name, type) \
struct name { \
/* 哈希表,可当做数组. */ \
struct type **hth_table; \
/* 哈希表 数组长度 */ \
unsigned hth_table_length; \
/* 元素个数 */ \
unsigned hth_n_entries; \
/* 最大扩容限制 */ \
unsigned hth_load_limit; \
/* 索引 */ \
int hth_prime_idx; \
}
#ifdef EVMAP_USE_HT
struct event_map_entry {
/*
struct
{
struct type *hte_next; // 构成链表
#ifndef HT_NO_CACHE_HASH_VALUES
unsigned hte_hash; // windows 下没有
#endif
}map_node;
HT_ENTRY(event_map_entry) map_node;
evutil_socket_t fd; // 文件描述符
union {
/*
#define LIST_HEAD(name, type) \
struct name
{ \
struct type *lh_first; /* first element */ \
}
#endif /* !LIST_HEAD */
struct evmap_io
{
// LIST_HEAD (event_dlist, event); 声明在上面
struct event_dlist events;
ev_uint16_t nread;
ev_uint16_t nwrite;
ev_uint16_t nclose;
};
struct evmap_io evmap_io; // 记录读写fd及数量
} ent;
};
struct event_iocp_port {
// 端口
HANDLE port;
// 临界区 锁
CRITICAL_SECTION lock;
// 线程数量
short n_threads;
// 关闭标志
short shutdown;
// 多久检查一次关闭和其他条件
long ms;
// 等待事件的线程
HANDLE *threads;
// 在当前端口上打开线程的数量
short n_live_threads;
// 完成关闭时发出的信号的信号量
HANDLE *shutdownSemaphore;
};
个人理解,不一定都是对的,仅供参考