事件集合(struct event_base)
struct event_base *event_base_new(void)
其中有很多的函数已经追踪阅读,但是没有展示,设计思想不难,但是代码由于#define的存在,有点复杂。
Order 0:struct event_base *event_base_new(void)
struct event_base * event_base_new(void)
{
struct event_base *base = NULL;
struct event_config *cfg = event_config_new(); //获取一个struct event_config对象
if (cfg) { //如果对象获取成功,根据config对struct event_base对象进行设置,然后free config object
base = event_base_new_with_config(cfg);
event_config_free(cfg);
}
return base;
}
Order 1:struct event_config* event_config_new(void)
和void event_config_free(struct event_config *cfg)
struct event_config* event_config_new(void)
{
struct event_config *cfg = mm_calloc(1, sizeof(*cfg)); //从自定义的alloc中分配一块空间用于存放config object
if (cfg == NULL) //如果分配失败,返回NULL
return (NULL);
TAILQ_INIT(&cfg->entries); //初始化config object的双向队列
cfg->max_dispatch_interval.tv_sec = -1; //如果为-1,则在没有事件时陷入等待,直到有事件发生。
cfg->max_dispatch_callbacks = INT_MAX; //将callback的处理限制为INT_MAX
cfg->limit_callbacks_after_prio = 1; //优先级默认为1,就是全局只有这么一个优先级
return (cfg);
}
void event_config_free(struct event_config *cfg)
{
struct event_config_entry *entry; //从config object中逐个取出struct event_config_entry对象(这个对象中没啥实际的东西)并删除
while ((entry = TAILQ_FIRST(&cfg->entries)) != NULL) {
TAILQ_REMOVE(&cfg->entries, entry, next);
event_config_entry_free(entry);
}
mm_free(cfg); //归还config Object内存
}
Order 1:struct event_base * event_base_new_with_config(const struct event_config *cfg)
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) { //获取存储struct event_base的对象
event_warn("%s: calloc", __func__);
return NULL;
}
if (cfg) //根据config对象设置event_base
base->flags = cfg->flags;
should_check_environment =
!(cfg && (cfg->flags & EVENT_BASE_FLAG_IGNORE_ENV)); //判断是否需要检查当前环境
{
struct timeval tmp;
int precise_time =
cfg && (cfg->flags & EVENT_BASE_FLAG_PRECISE_TIMER); //检查是否设置了精确时间的选项
int flags;
if (should_check_environment && !precise_time) {
precise_time = evutil_getenv_("EVENT_PRECISE_TIMER") != NULL;
base->flags |= EVENT_BASE_FLAG_PRECISE_TIMER;
}
flags = precise_time ? EV_MONOT_PRECISE : 0; //判断是否需要精确时间选项
evutil_configure_monotonic_time_(&base->monotonic_timer, flags); //配置那个为空的对象
gettime(base, &tmp); //获取时间
}
min_heap_ctor_(&base->timeheap); //将超时时间以最小堆组织起来
base->sig.ev_signal_pair[0] = -1; //将sockpair处理的事件机制的fd初始化为-1
base->sig.ev_signal_pair[1] = -1;
base->th_notify_fd[0] = -1;
base->th_notify_fd[1] = -1;
TAILQ_INIT(&base->active_later_queue); //初始化下一轮循环通知的事件初始化
evmap_io_initmap_(&base->io); //初始化IO事件map(HASH)
evmap_signal_initmap_(&base->sigmap); //初始化信号事件(HASH)
event_changelist_init_(&base->changelist); //初始化事件修改链表
base->evbase = NULL; //将指向特定数据的指针初始化为NULL
if (cfg) {
memcpy(&base->max_dispatch_time,
&cfg->max_dispatch_interval, sizeof(struct timeval)); //根据config对象,初始化struct event_base的:
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; //初始化优先级数量
for (i = 0; eventops[i] && !base->evbase; i++) { //eventops是一个全局数据结构,如果全局数据结构存在并且base的私有数据不存在,就执行代码
if (cfg != NULL) { //如果有config object
if (event_config_is_avoided_method(cfg,
eventops[i]->name)) //将eventop中的name字符串,传递给配置对象
continue;
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;
base->evsel = eventops[i]; //将信号处理ops注册给base的信号处理ops
base->evbase = base->evsel->init(base); //私有数据 = struct event_base对象??有可能是反向获取struct event_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 */
#if !defined(EVENT__DISABLE_THREAD_SUPPORT) && !defined(EVENT__DISABLE_DEBUG_MODE)
event_debug_created_threadable_ctx_ = 1;
#endif
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); //这个函数会初始化与唤醒主线程的sockpair以及注册唤醒主线程的函数,都不难,可以很快用C++实现
if (r<0) {
event_warnx("%s: Unable to make base notifiable.", __func__);
event_base_free(base);
return NULL;
}
}
return (base); //返回已经初始化的struct event_base对象
}
void event_base_free(struct event_base *base)
Order 0:void event_base_free(struct event_base *base)
void event_base_free(struct event_base *base)
{
event_base_free_(base, 1);
}
Order 1:static void event_base_free_(struct event_base *base, int run_finalizers)
static void event_base_free_(struct event_base *base, int run_finalizers)
{
int i, n_deleted=0;
struct event *ev;
if (base == NULL && current_base) //获取现有的struct event_base对象
base = current_base;
if (base == NULL) {
event_warnx("%s: no base to free", __func__);
return;
}
if (base->th_notify_fd[0] != -1) { //在事件库中存在多个线程,终止时需要合理的处理这些线程
event_del(&base->th_notify); //从事件队列中删除与多线程通信的事件
EVUTIL_CLOSESOCKET(base->th_notify_fd[0]); //关闭管道fd
if (base->th_notify_fd[1] != -1)
EVUTIL_CLOSESOCKET(base->th_notify_fd[1]); //关闭管道fd
base->th_notify_fd[0] = -1;
base->th_notify_fd[1] = -1;
event_debug_unassign(&base->th_notify); //测试这个event是否已经取消注册
}
evmap_delete_all_(base); //删除事件链表中所有的IO事件与信号事件
while ((ev = min_heap_top_(&base->timeheap)) != NULL) { //从最小堆中删除所有的超时事件
event_del(ev);
++n_deleted;
}
for (i = 0; i < base->n_common_timeouts; ++i) { //这个管理超时事件的common没有搞懂
struct common_timeout_list *ctl =
base->common_timeout_queues[i];
event_del(&ctl->timeout_event); /* Internal; doesn't count */
event_debug_unassign(&ctl->timeout_event);
for (ev = TAILQ_FIRST(&ctl->events); ev; ) {
struct event *next = TAILQ_NEXT(ev,
ev_timeout_pos.ev_next_with_common_timeout);
if (!(ev->ev_flags & EVLIST_INTERNAL)) {
event_del(ev);
++n_deleted;
}
ev = next;
}
mm_free(ctl);
}
if (base->common_timeout_queues) //释放公共超时事件队列
mm_free(base->common_timeout_queues);
for (;;) { //回收处理事件的线程资源
int i = event_base_free_queues_(base, run_finalizers);
if (!i) {
break;
}
n_deleted += i;
}
if (n_deleted)
event_debug(("%s: %d events were still set in base",
__func__, n_deleted));
while (LIST_FIRST(&base->once_events)) { //从只注册一次的事件,但是事件还没有发生的链表中,逐个删除事件
struct event_once *eonce = LIST_FIRST(&base->once_events);
LIST_REMOVE(eonce, next_once);
mm_free(eonce);
}
if (base->evsel != NULL && base->evsel->dealloc != NULL)
base->evsel->dealloc(base); //使用注册的函数清理base
for (i = 0; i < base->nactivequeues; ++i) //在销毁struct event_base对象之前,逐个清理
EVUTIL_ASSERT(TAILQ_EMPTY(&base->activequeues[i]));
EVUTIL_ASSERT(min_heap_empty_(&base->timeheap)); //在销毁之前,确保最小堆已经被清理干净
min_heap_dtor_(&base->timeheap); //销毁最小堆
mm_free(base->activequeues); //释放活动事件队列
evmap_io_clear_(&base->io); //清理IO事件队列
evmap_signal_clear_(&base->sigmap); //清理信号事件队列
event_changelist_freemem_(&base->changelist); //清理改变事件队列
EVTHREAD_FREE_LOCK(base->th_base_lock, 0); //释放锁与条件变量
EVTHREAD_FREE_COND(base->current_event_cond);
if (base == current_base)
current_base = NULL;
mm_free(base);
}
int event_reinit(struct event_base *base)
Order 0:int event_reinit(struct event_base *base)
int event_reinit(struct event_base *base)
{
const struct eventop *evsel;
int res = 0;
int was_notifiable = 0;
int had_signal_added = 0;
EVBASE_ACQUIRE_LOCK(base, th_base_lock); //获取锁
evsel = base->evsel; //获取处理事件的ops
if (evsel->need_reinit) { //如果struct event_base对象在fork之后需要重新进行处理
base->evsel = &nil_eventop; //获取信号处理
}
if (base->sig.ev_signal_added) {
event_del_nolock_(&base->sig.ev_signal, EVENT_DEL_AUTOBLOCK);
event_debug_unassign(&base->sig.ev_signal);
memset(&base->sig.ev_signal, 0, sizeof(base->sig.ev_signal));
had_signal_added = 1;
base->sig.ev_signal_added = 0;
}
if (base->sig.ev_signal_pair[0] != -1)
EVUTIL_CLOSESOCKET(base->sig.ev_signal_pair[0]);
if (base->sig.ev_signal_pair[1] != -1)
EVUTIL_CLOSESOCKET(base->sig.ev_signal_pair[1]);
if (base->th_notify_fn != NULL) {
was_notifiable = 1;
base->th_notify_fn = NULL;
}
if (base->th_notify_fd[0] != -1) {
event_del_nolock_(&base->th_notify, EVENT_DEL_AUTOBLOCK);
EVUTIL_CLOSESOCKET(base->th_notify_fd[0]);
if (base->th_notify_fd[1] != -1)
EVUTIL_CLOSESOCKET(base->th_notify_fd[1]);
base->th_notify_fd[0] = -1;
base->th_notify_fd[1] = -1;
event_debug_unassign(&base->th_notify);
}
/* Replace the original evsel. */
base->evsel = evsel;
if (evsel->need_reinit) {
/* Reconstruct the backend through brute-force, so that we do
* not share any structures with the parent process. For some
* backends, this is necessary: epoll and kqueue, for
* instance, have events associated with a kernel
* structure. If didn't reinitialize, we'd share that
* structure with the parent process, and any changes made by
* the parent would affect our backend's behavior (and vice
* versa).
*/
if (base->evsel->dealloc != NULL)
base->evsel->dealloc(base);
base->evbase = evsel->init(base);
if (base->evbase == NULL) {
event_errx(1,
"%s: could not reinitialize event mechanism",
__func__);
res = -1;
goto done;
}
/* Empty out the changelist (if any): we are starting from a
* blank slate. */
event_changelist_freemem_(&base->changelist);
/* Tell the event maps to re-inform the backend about all
* pending events. This will make the signal notification
* event get re-created if necessary. */
if (evmap_reinit_(base) < 0)
res = -1;
} else {
res = evsig_init_(base);
if (res == 0 && had_signal_added) {
res = event_add_nolock_(&base->sig.ev_signal, NULL, 0);
if (res == 0)
base->sig.ev_signal_added = 1;
}
}
/* If we were notifiable before, and nothing just exploded, become
* notifiable again. */
if (was_notifiable && res == 0)
res = evthread_make_base_notifiable_nolock_(base);
done:
EVBASE_RELEASE_LOCK(base, th_base_lock);
return (res);
}