Libevent源码剖析(三)

事件集合(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);
}

猜你喜欢

转载自www.cnblogs.com/ukernel/p/9191078.html