首先在main函数中,我们调用event_base_new函数来创建一个event_base对象,一个event_base对象就是一个Reactor实例。
event_base_new函数的流程:
1、创建一个config对象
2、把config对象作为参数,调用event_base_new_with_config函数来创建一个event_base对象
创建config对象的流程如下:
最重要的event_base_new_with_config函数用于创建一个event_base对象
event_base_new函数的流程:
1、创建一个config对象
2、把config对象作为参数,调用event_base_new_with_config函数来创建一个event_base对象
3、释放config对象
// 创建一个Reactor实例
struct event_base * event_base_new(void)
{
struct event_base *base = NULL;
// 新建实例的配置
struct event_config *cfg = event_config_new();
if (cfg) {
// 使用该配置初始化Reactor实例
base = event_base_new_with_config(cfg);
// 释放配置
event_config_free(cfg);
}
return base;
}
创建config对象的流程如下:
// 创建一个被Reactor实例使用的配置对象
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);
return (cfg);
}
event_config的定义如下:
struct event_config {
TAILQ_HEAD(event_configq, event_config_entry) entries;
// cpu核数
int n_cpus_hint;
// event的一些特征
enum event_method_feature require_features;
// event_base的配置标志
enum event_base_config_flag flags;
};
event_method_feature和event_base_config_flag分别定义如下:
// 事件处理器的方法的特征
enum event_method_feature {
/** Require an event method that allows edge-triggered events with EV_ET. */
// 边沿触发(针对epoll)
EV_FEATURE_ET = 0x01,
EV_FEATURE_O1 = 0x02,
/** Require an event method that allows file descriptors as well as
* sockets. */
// 允许文件描述符以及套接字
EV_FEATURE_FDS = 0x04
};
// 配置标志
enum event_base_config_flag {
// 非阻塞
EVENT_BASE_FLAG_NOLOCK = 0x01,
// 忽略环境
EVENT_BASE_FLAG_IGNORE_ENV = 0x02,
// 启动IOCP
EVENT_BASE_FLAG_STARTUP_IOCP = 0x04,
// 不缓存系统事件
EVENT_BASE_FLAG_NO_CACHE_TIME = 0x08,
// epoll使用changelist
EVENT_BASE_FLAG_EPOLL_USE_CHANGELIST = 0x10
};
最重要的event_base_new_with_config函数用于创建一个event_base对象
// 使用配置创建一个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
// 分配内存
if ((base = mm_calloc(1, sizeof(struct event_base))) == NULL)
{
event_warn("%s: calloc", __func__);
return NULL;
}
// 时间检测
detect_monotonic();
// 获取时间
gettime(base, &base->event_tv);
// 构造小根堆
min_heap_ctor(&base->timeheap);
// 初始化事件处理器队列
TAILQ_INIT(&base->eventqueue);
// 被信号所使用的管道
base->sig.ev_signal_pair[0] = -1;
base->sig.ev_signal_pair[1] = -1;
// 使用多线程的时候,这两个用于通知
base->th_notify_fd[0] = -1;
base->th_notify_fd[1] = -1;
// 初始化存放延迟回调函数的链表
event_deferred_cb_queue_init(&base->defer_queue);
// 通知的回调函数
base->defer_queue.notify_fn = notify_base_cbq_callback;
// 通知回调函数的参数
base->defer_queue.notify_arg = base;
// 设置标志
if (cfg)
base->flags = cfg->flags;
// 存放 事件以及事件处理器映射关系 的容器的初始化
evmap_io_initmap(&base->io);
// 存放 信号值和信号事件之间的映射关系 的容器的初始化
evmap_signal_initmap(&base->sigmap);
// 事件变化队列初始化
event_changelist_init(&base->changelist);
// 后台的io复用机制
base->evbase = NULL;
// 是否需要检测环境变量
should_check_environment = !(cfg && (cfg->flags & EVENT_BASE_FLAG_IGNORE_ENV));
// 从众多的io复用机制中选择一个最高效的后台io复用机制
for (i = 0; eventops[i] && !base->evbase; i++)
{
// 如果配置不为空,则所选的io复用用机制,必须满足配置的要求
if (cfg != NULL)
{
/* determine if this backend should be avoided */
// 检测某一个后台io复用机制是否应该被避免使用
if (event_config_is_avoided_method(cfg,eventops[i]->name))
continue;
// 如果某个io复用机制的某些特征不满足所要求的特征,则跳过
if ((eventops[i]->features & cfg->require_features)!= cfg->require_features)
continue;
}
/* also obey the environment variables */
// 必须满足环境变量的要求
if (should_check_environment && event_is_method_disabled(eventops[i]->name))
continue;
// 选中了某一个高效的io复用机制
base->evsel = eventops[i];
// 初始化
base->evbase = base->evsel->init(base);
}
if (base->evbase == NULL)
{
event_warnx("%s: no event mechanism available",
__func__);
base->evsel = NULL;
event_base_free(base);
return NULL;
}
if (evutil_getenv("EVENT_SHOW_METHOD"))
event_msgx("libevent using: %s", base->evsel->name);
// 优先级初始化
/* allocate a single active event queue */
if (event_base_priority_init(base, 1) < 0)
{
event_base_free(base);
return NULL;
}
/* prepare for threading */
// 支持多线程
#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,
EVTHREAD_LOCKTYPE_RECURSIVE);
base->defer_queue.lock = base->th_base_lock;
// 分配一个条件变量
EVTHREAD_ALLOC_COND(base->current_event_cond);
// 设置event_base是否可以被通知
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);
}