目录
event_base_new
event_config
event_base_new_with_config
struct event_base *
event_base_new(void)
{
struct event_base *base = NULL; // 初始化一个event_base
struct event_config *cfg = event_config_new(); // 看下文注解
if (cfg) {
base = event_base_new_with_config(cfg); // 将event_config 绑定到base上
event_config_free(cfg); // 资源释放
}
return base;
}
struct event_config_entry {
TAILQ_ENTRY(event_config_entry) next; // 下一个屏蔽的后台
const char *avoid_method; // 屏蔽的后台名字
};
struct event_config {
// 屏蔽后台的双向队列
TAILQ_HEAD(event_configq, event_config_entry) entries;
// 建议的cpu数量,不强制
int n_cpus_hint;
// 最大调度间隔
struct timeval max_dispatch_interval;
int max_dispatch_callbacks; // 事件循环中可以处理最大的回调数量
int limit_callbacks_after_prio; // 回调函数优先级限制
// 用于描述 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 require_features;
/*
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 event_config *
event_config_new(void) // 这好像没什么好说的
{
struct event_config *cfg = mm_calloc(1, sizeof(*cfg));
if (cfg == NULL)
return (NULL);
TAILQ_INIT(&cfg->entries); // 初始化屏蔽后端的双向队列
cfg->max_dispatch_interval.tv_sec = -1;
cfg->max_dispatch_callbacks = INT_MAX;
cfg->limit_callbacks_after_prio = 1;
return (cfg);
}
// 使用本函数初始化新的event_base,可以使用配置对象来屏蔽某些特定的时间通知
struct event_base *
event_base_new_with_config(const struct event_config *cfg)
{
int i;
struct event_base *base;
int should_check_environment; // 需要检查的环境
#ifndef EVENT__DISABLE_DEBUG_MODE
event_debug_mode_too_late = 1;
#endif
// 申请空间并初始化 对每个域都赋值1
if ((base = mm_calloc(1, sizeof(struct event_base))) == NULL) {
event_warn("%s: calloc", __func__);
return NULL;
}
if (cfg) // 把传进来的参数 event_config 简单的给event_base赋个值
base->flags = cfg->flags;
// 赋值是否需要进行环境检查,默认情况下是没有设置EVENT_BASE_FLAG_IGNORE_ENV的
// 所以 should_check_enviroment = 1 检查环境变量
should_check_environment =
!(cfg && (cfg->flags & EVENT_BASE_FLAG_IGNORE_ENV));
{ // 检查时间是否发生变化
struct timeval tmp;
// 如果使用精确时间,则precise_time = 1
int precise_time =
cfg && (cfg->flags & EVENT_BASE_FLAG_PRECISE_TIMER);
int flags;
if (should_check_environment && !precise_time) {
// evutil_getenv_ (getenv)获取环境变量
precise_time = evutil_getenv_("EVENT_PRECISE_TIMER") != NULL;
if (precise_time) {
base->flags |= EVENT_BASE_FLAG_PRECISE_TIMER;
}
}
// 默认情况下 precise_time = 1 既 flags = EV_MONOT_PRECISE
flags = precise_time ? EV_MONOT_PRECISE : 0;
// 配置单调递增的时间,默认情况下,会使用EV_MONOTONIC模式获取系统时间,并将event_base的monotonic_clock模式设置为EV_MONOTONIC;
evutil_configure_monotonic_time_(&base->monotonic_timer, flags);
// 获取当前event_base中缓存的时间,并设置使用系统时间更新event_base缓存时间的时间间隔,并获取当前系统的monotonic时间和当前系统的real时间之间差值并存储在event_base中
gettime(base, &tmp);
}
// 创建时间最小堆
min_heap_ctor_(&base->timeheap);
// 内部信号通知的管道 0读1写
base->sig.ev_signal_pair[0] = -1;
base->sig.ev_signal_pair[1] = -1;
// 内部线程通知的文件描述符 0读1写
base->th_notify_fd[0] = -1;
base->th_notify_fd[1] = -1;
// 初始化下一次激活的队列
TAILQ_INIT(&base->active_later_queue);
// 初始化io事件的映射
// base->io = event_io_map
// 如果在windows环节下,event_io_map会使用哈希结构
// 否则当成 event_signal_map 来使用
evmap_io_initmap_(&base->io);
// 初始化信号到事件的映射
evmap_signal_initmap_(&base->sigmap);
// 初始化变化时间列表
event_changelist_init_(&base->changelist);
// 后端方法初始化
base->evbase = NULL;
// 把传进来的参数 event_config 简单的给event_base赋个值
if (cfg) {
memcpy(&base->max_dispatch_time,
&cfg->max_dispatch_interval, sizeof(struct timeval));
base->limit_callbacks_after_prio =
cfg->limit_callbacks_after_prio;
} else {
base->max_dispatch_time.tv_sec = -1;
base->limit_callbacks_after_prio = 1;
}
if (cfg && cfg->max_dispatch_callbacks >= 0) {
base->max_dispatch_callbacks = cfg->max_dispatch_callbacks;
} else {
base->max_dispatch_callbacks = INT_MAX;
}
if (base->max_dispatch_callbacks == INT_MAX &&
base->max_dispatch_time.tv_sec == -1)
base->limit_callbacks_after_prio = INT_MAX;
// 对base的后端方法进行初始化
for (i = 0; eventops[i] && !base->evbase; i++) {
if (cfg != NULL) {
// 跳过屏蔽的后端方法
if (event_config_is_avoided_method(cfg,
eventops[i]->name))
continue;
// 跳过与配置不符合的工作特征的后端
if ((eventops[i]->features & cfg->require_features)
!= cfg->require_features)
continue;
}
// 跳过环境不支持的后端
if (should_check_environment &&
event_is_method_disabled(eventops[i]->name))
continue;
// 选择一个后端,只会选一个
base->evsel = eventops[i];
// 调用相应后端方法的初始化函数进行初始化
/* 例如epoll
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
};
*/
base->evbase = base->evsel->init(base);
}
// 如果没有发现能用的后端方法 释放资源后返回 NULL
if (base->evbase == NULL) {
event_warnx("%s: no event mechanism available",
__func__); // 报错
base->evsel = NULL;
event_base_free(base); // 释放资源
return NULL;
}
// 获取环境变量 EVENT_SHOW_METHOD。打印后端方法名字
if (evutil_getenv_("EVENT_SHOW_METHOD"))
event_msgx("libevent using: %s", base->evsel->name);
// 分配一个事件优先队列,初始个数为1
if (event_base_priority_init(base, 1) < 0) {
event_base_free(base);
return NULL;
}
// 准备线程
#if !defined(EVENT__DISABLE_THREAD_SUPPORT) && !defined(EVENT__DISABLE_DEBUG_MODE)
event_debug_created_threadable_ctx_ = 1;
#endif
#ifndef EVENT__DISABLE_THREAD_SUPPORT
if (EVTHREAD_LOCKING_ENABLED() &&
(!cfg || !(cfg->flags & EVENT_BASE_FLAG_NOLOCK))) {
int r;
EVTHREAD_ALLOC_LOCK(base->th_base_lock, 0);
EVTHREAD_ALLOC_COND(base->current_event_cond);
r = evthread_make_base_notifiable(base);
if (r<0) {
event_warnx("%s: Unable to make base notifiable.", __func__);
event_base_free(base);
return NULL;
}
}
#endif
#ifdef _WIN32
if (cfg && (cfg->flags & EVENT_BASE_FLAG_STARTUP_IOCP))
event_base_start_iocp_(base, cfg->n_cpus_hint);
#endif
return (base);
}
参考文章 https://blog.csdn.net/qq_34768693/article/details/119861542 Libevent 源码学习笔记(1) event 与 event_base