libevent事件主循环

event_base_dispatch启动循环,其实是调用了event_base_loop

int
event_base_dispatch(struct event_base *event_base)
{
    return (event_base_loop(event_base, 0));
}
int
event_base_loop(struct event_base *base, int flags)
{
    /*evsel为base中操作IO复用的结构,下面封装了下面几个函数,编译时指定I/O复用后,无论是epoll还是kequeue等,都要实现这几个方法
    void *(*init)(struct event_base *);
    int (*add)(struct event_base *, evutil_socket_t fd, short old, short events, void *fdinfo);
    int (*del)(struct event_base *, evutil_socket_t fd, short old, short events, void *fdinfo);
    int (*dispatch)(struct event_base *, struct timeval *);
    */
    const struct eventop *evsel = base->evsel;
    struct timeval tv;
    struct timeval *tv_p;
    int res, done, retval = 0;
//防止多线程重入--start
    EVBASE_ACQUIRE_LOCK(base, th_base_lock);

    if (base->running_loop) {
        event_warnx("%s: reentrant invocation.  Only one event_base_loop"
            " can run on each event_base at once.", __func__);
        EVBASE_RELEASE_LOCK(base, th_base_lock);
        return -1;
    }

    base->running_loop = 1;
//防止多线程重入--end
//time cache置零
    clear_time_cache(base);


    if (base->sig.ev_signal_added && base->sig.ev_n_signals_added)
        evsig_set_base(base);

    done = 0;

#ifndef _EVENT_DISABLE_THREAD_SUPPORT
    base->th_owner_id = EVTHREAD_GET_ID();
#endif

    base->event_gotterm = base->event_break = 0;
//防止多线程重入
    while (!done) {
        base->event_continue = 0;

        /* Terminate the loop if we have been asked to */
        if (base->event_gotterm) {
            break;
        }

        if (base->event_break) {
            break;
        }
/*时间校正,如5点添加了事件,而后用户改动了时间到2点,则表明时间出了问题,将时间小根堆    里的全部时间减3*/
        timeout_correct(base, &tv);

        tv_p = &tv;
        if (!N_ACTIVE_CALLBACKS(base) && !(flags & EVLOOP_NONBLOCK)) {
            timeout_next(base, &tv_p);
        } else {
            /*
             有已经激活的事件或者延迟回调没执行则清除时间缓存退出
             */
            evutil_timerclear(&tv);
        }

        /* If we have no events, we just exit */
        if (!event_haveevents(base) && !N_ACTIVE_CALLBACKS(base)) {
            event_debug(("%s: no events registered.", __func__));
            retval = 1;
            goto done;
        }

        /* last wait time置为time cache,cache没有则获取系统时间 */
        gettime(base, &base->event_tv);
        //清除time cache
        clear_time_cache(base);
        //IO复用如epoll_wait执行一次
        res = evsel->dispatch(base, tv_p);

        if (res == -1) {
            event_debug(("%s: dispatch returned unsuccessfully.",
                __func__));
            retval = -1;
            goto done;
        }
        //更新cache,设为当前时间

        update_time_cache(base);
        //查找小根堆,超时时间的事件清除并加入激活时间队列
        //event_active_nolock(ev, EV_TIMEOUT, 1);
        timeout_process(base);

        //event_process_active执行激活列表activequeues[priority]中事件的回调
        if (N_ACTIVE_CALLBACKS(base)) {
            int n = event_process_active(base);
            if ((flags & EVLOOP_ONCE)
                && N_ACTIVE_CALLBACKS(base) == 0
                && n != 0)
                done = 1;
        } else if (flags & EVLOOP_NONBLOCK)
            done = 1;
    }
    event_debug(("%s: asked to terminate loop.", __func__));

done:
    clear_time_cache(base);
    base->running_loop = 0;

    EVBASE_RELEASE_LOCK(base, th_base_lock);

    return (retval);
}
  • 下面这个数据结构是libevent能管理信号事件的关键
/* 
struct evsig_info {
    // 用来监视下面ev_signal_pair[1]的事件 
    struct event ev_signal;

    /*设置了socketpair,且在 signal.c :373中定义了
    evsig_handler{
    ...
    signal(sig, evsig_handler);
    msg = sig;
    send(evsig_base_fd, (char*)&msg, 1, 0);
    errno = save_errno;
    ...
    }
    posix风格的signal函数使得当接收到信号sig时,调用本函数将sig(int类型)发送至evsig_base_fd( = base->sig.ev_signal_pair[0]),从而激活socketpair[1]的可读事件从而达到将signal加入事件循环的目的
    */
    evutil_socket_t ev_signal_pair[2];
    //True iff we've added the ev_signal event yet.  
    int ev_signal_added;
    //Count of the number of signals we're currently watching. 
    int ev_n_signals_added;

    /* Array of previous signal handler objects before Libevent started
     * messing with them.  Used to restore old signal handlers. */
#ifdef _EVENT_HAVE_SIGACTION
    struct sigaction **sh_old;
#else
    ev_sighandler_t **sh_old;
#endif

    int sh_old_max;
};
*/
  • 时间缓存 time_cache
    while(!done){

    }
    此循环每次开始都会检查done变量,如果有事件激活则进入下方的event_process_active,done会置1,循环结束;若没事件激活则一直循环,循环中,每次判断进入event_process_active之前会更新time_cache,则下次进入循环就一直使用该时间作为当前时间,不必每次都调用gettimeofday(glibc 函数,不是系统调用)
    参考浅谈时间函数gettimeofday的成本
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值