libevent(四)event_base_loop

暂时不分析超时

int
event_base_loop(struct event_base *base, int flags)
{
    const struct eventop *evsel = base->evsel;
    struct timeval tv;
    struct timeval *tv_p;
    int res, done, retval = 0;


    /* Grab the lock.  We will release it inside evsel.dispatch, and again
     * as we invoke user callbacks. */
    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;


    clear_time_cache(base);//base->tv_cache.tv_sec = 0;


    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;
        base->n_deferreds_queued = 0;


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


        if (base->event_break) {
            break;
        }


        tv_p = &tv;
        if (!N_ACTIVE_CALLBACKS(base) && !(flags & EVLOOP_NONBLOCK)) {
            timeout_next(base, &tv_p);
        } else {
            /*
             * if we have active events, we just poll new events
             * without waiting.
             */
            evutil_timerclear(&tv);
        }


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


        event_queue_make_later_events_active(base);
        clear_time_cache(base);


        res = evsel->dispatch(base, tv_p);


        if (res == -1) {
            event_debug(("%s: dispatch returned unsuccessfully.",
                __func__));
            retval = -1;
            goto done;
        }


        update_time_cache(base);


        timeout_process(base);


        if (N_ACTIVE_CALLBACKS(base)) {//if (((base)->event_count_active))
            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);
}

接下来看看select的dispatch函数

static int
select_dispatch(struct event_base *base, struct timeval *tv)
{
    int res=0, i, j, nfds;
    struct selectop *sop = base->evbase;//获取select复用对应结构体,evbase中保存了所有注册到该event_base的文件描述符


    check_selectop(sop);
    if (sop->resize_out_sets) {
        fd_set *readset_out=NULL, *writeset_out=NULL;
        size_t sz = sop->event_fdsz;
        if (!(readset_out = mm_realloc(sop->event_readset_out, sz)))
            return (-1);
        sop->event_readset_out = readset_out;
        if (!(writeset_out = mm_realloc(sop->event_writeset_out, sz))) {
            /* We don't free readset_out here, since it was
             * already successfully reallocated. The next time
             * we call select_dispatch, the realloc will be a
             * no-op. */
            return (-1);
        }
        sop->event_writeset_out = writeset_out;
        sop->resize_out_sets = 0;
    }//内存分配


    memcpy(sop->event_readset_out, sop->event_readset_in,
           sop->event_fdsz);
    memcpy(sop->event_writeset_out, sop->event_writeset_in,
           sop->event_fdsz);//加入文件描述符到对应out数组


    nfds = sop->event_fds+1;


    EVBASE_RELEASE_LOCK(base, th_base_lock);
    res = select(nfds, sop->event_readset_out,
        sop->event_writeset_out, NULL, tv);//select调用将阻塞在这里


    EVBASE_ACQUIRE_LOCK(base, th_base_lock);


    check_selectop(sop);


    if (res == -1) {
        if (errno != EINTR) {
            event_warn("select");
            return (-1);
        }


        return (0);
    }


    event_debug(("%s: select reports %d", __func__, res));


    check_selectop(sop);
    i = evutil_weakrand_range_(&base->weakrand_seed, nfds);
    for (j = 0; j < nfds; ++j) {//当阻塞返回时,位数组event_readset_out和event_writest_out的非0位对应的位置即发生响应的文件描述符的值
        if (++i >= nfds)
            i = 0;
        res = 0;
        if (FD_ISSET(i, sop->event_readset_out))
            res |= EV_READ;
        if (FD_ISSET(i, sop->event_writeset_out))
            res |= EV_WRITE;


        if (res == 0)
            continue;


        evmap_io_active_(base, i, res);
    }
    check_selectop(sop);
  return (0);
}

函数evmap_io_active:

void
evmap_io_active_(struct event_base *base, evutil_socket_t fd, short events)
{       
    struct event_io_map *io = &base->io;
    struct evmap_io *ctx;
    struct event *ev;
            
#ifndef EVMAP_USE_HT
    if (fd < 0 || fd >= io->nentries)
        return;
#endif
    GET_IO_SLOT(ctx, io, fd, evmap_io);//(ctx) = (struct evmap_io *)((io)->entries[fd]);
   
    if (NULL == ctx)
        return;
    LIST_FOREACH(ev, &ctx->events, ev_io_next) {//遍历此fd的eventlist链表,通过events的值执行相应的回调函数
        if (ev->ev_events & events)
            event_active_nolock_(ev, ev->ev_events & events, 1);
    }
}

函数event_active_nolock_

void
event_active_nolock_(struct event *ev, int res, short ncalls)
{
    struct event_base *base;


    event_debug(("event_active: %p (fd "EV_SOCK_FMT"), res %d, callback %p",
        ev, EV_SOCK_ARG(ev->ev_fd), (int)res, ev->ev_callback));


    base = ev->ev_base;
    EVENT_BASE_ASSERT_LOCKED(base);


    if (ev->ev_flags & EVLIST_FINALIZING) {
        /* XXXX debug */
        return;
    }


    switch ((ev->ev_flags & (EVLIST_ACTIVE|EVLIST_ACTIVE_LATER))) {
    default:
    case EVLIST_ACTIVE|EVLIST_ACTIVE_LATER:
        EVUTIL_ASSERT(0);
        break;
    case EVLIST_ACTIVE:
        /* We get different kinds of events, add them together */
        ev->ev_res |= res;
        return;
    case EVLIST_ACTIVE_LATER:
        ev->ev_res |= res;
        break;
    case 0:
        ev->ev_res = res;
        break;
    }


    if (ev->ev_pri < base->event_running_priority)
        base->event_continue = 1;


    if (ev->ev_events & EV_SIGNAL) {
#ifndef EVENT__DISABLE_THREAD_SUPPORT
        if (base->current_event == event_to_event_callback(ev) &&
            !EVBASE_IN_THREAD(base)) {
            ++base->current_event_waiters;
            EVTHREAD_COND_WAIT(base->current_event_cond, base->th_base_lock);
        }
#endif
        ev->ev_ncalls = ncalls;
        ev->ev_pncalls = NULL;
    }


    event_callback_activate_nolock_(base, event_to_event_callback(ev));
}

函数event_callback_activate_nolock_

int
event_callback_activate_nolock_(struct event_base *base,
    struct event_callback *evcb)
{
    int r = 1;


    if (evcb->evcb_flags & EVLIST_FINALIZING)
        return 0;


    switch (evcb->evcb_flags & (EVLIST_ACTIVE|EVLIST_ACTIVE_LATER)) {
    default:
        EVUTIL_ASSERT(0);
        EVUTIL_FALLTHROUGH;
    case EVLIST_ACTIVE_LATER:
        event_queue_remove_active_later(base, evcb);
        r = 0;
        break;
    case EVLIST_ACTIVE:
        return 0;
    case 0:
        break;
    }


    event_queue_insert_active(base, evcb);//


    if (EVBASE_NEED_NOTIFY(base))
        evthread_notify_base(base);


    return r;
}

函数event_queue_insert_active:

static void
event_queue_insert_active(struct event_base *base, struct event_callback *evcb)
{
    EVENT_BASE_ASSERT_LOCKED(base);


    if (evcb->evcb_flags & EVLIST_ACTIVE) {
        /* Double insertion is possible for active events */
        return;
    }

    do {
     ((base)->event_count += !((evcb->evcb_flags) & 0x10));
     (base)->event_count_max = ((((base)->event_count_max)>((base)->event_count))?
((base)->event_count_max):((base)->event_count));
} while (0);

    evcb->evcb_flags |= EVLIST_ACTIVE;


    base->event_count_active++;
    
    base->event_count_active_max = (((base->event_count_active_max)>(base-           >event_count_active))?(base->event_count_active_max):(base->event_count_active));

    EVUTIL_ASSERT(evcb->evcb_pri < base->nactivequeues);
    do
    {
         (evcb)->evcb_active_next.tqe_next = ((void *)0); 
         (evcb)->evcb_active_next.tqe_prev= (&base->activequeues[evcb->evcb_pri])->tqh_last;
         *(&base->activequeues[evcb->evcb_pri])->tqh_last = (evcb);
         (&base->activequeues[evcb->evcb_pri])->tqh_last = &(evcb)->evcb_active_next.        
    tqe_next;
    } while ( 0);//插入evcb到激活队列
}

函数event_process_active执行激活队列函数

static int
event_process_active(struct event_base *base)
{
    /* Caller must hold th_base_lock */
    struct evcallback_list *activeq = NULL;
    int i, c = 0;
    const struct timeval *endtime;
    struct timeval tv;
    const int maxcb = base->max_dispatch_callbacks;
    const int limit_after_prio = base->limit_callbacks_after_prio;
    if (base->max_dispatch_time.tv_sec >= 0) {
        update_time_cache(base);
        gettime(base, &tv);
        evutil_timeradd(&base->max_dispatch_time, &tv, &tv);
        endtime = &tv;
    } else {
        endtime = NULL;
    }


    for (i = 0; i < base->nactivequeues; ++i) {
        if (TAILQ_FIRST(&base->activequeues[i]) != NULL) {
            base->event_running_priority = i;
            activeq = &base->activequeues[i];//从低序号(高优先级)数组开始执行
            if (i < limit_after_prio)
                c = event_process_active_single_queue(base, activeq,
                    INT_MAX, NULL);
            else
                c = event_process_active_single_queue(base, activeq,
                    maxcb, endtime);
            if (c < 0) {
                goto done;
            } else if (c > 0)
                break; /* Processed a real event; do not
                    * consider lower-priority events */
...

函数event_process_active_single_queue

static int
event_process_active_single_queue(struct event_base *base,
    struct evcallback_list *activeq,
    int max_to_process, const struct timeval *endtime)
{
    struct event_callback *evcb;
    int count = 0;


    EVUTIL_ASSERT(activeq != NULL);


    for (evcb = TAILQ_FIRST(activeq); evcb; evcb = TAILQ_FIRST(activeq)) {
        struct event *ev=NULL;
        if (evcb->evcb_flags & EVLIST_INIT) {
            ev = event_callback_to_event(evcb);


            if (ev->ev_events & EV_PERSIST || ev->ev_flags & EVLIST_FINALIZING)
                event_queue_remove_active(base, evcb);
            else
                event_del_nolock_(ev, EVENT_DEL_NOBLOCK);//该函数会直接将event从对应的fd的event链表中移除,依然存在于全局链表,可以再次event_add
            event_debug((
                "event_process_active: event: %p, %s%s%scall %p",
...
        switch (evcb->evcb_closure) {
        case EV_CLOSURE_EVENT_SIGNAL:
            EVUTIL_ASSERT(ev != NULL);
            event_signal_closure(base, ev);
            break;
        case EV_CLOSURE_EVENT_PERSIST:
            EVUTIL_ASSERT(ev != NULL);
            event_persist_closure(base, ev);//该函数会将event再次加入到对应的fd中
            break;
        case EV_CLOSURE_EVENT: {
            void (*evcb_callback)(evutil_socket_t, short, void *);
            short res;
            EVUTIL_ASSERT(ev != NULL);
            evcb_callback = *ev->ev_callback;
            res = ev->ev_res;
            EVBASE_RELEASE_LOCK(base, th_base_lock);
            evcb_callback(ev->ev_fd, res, ev->ev_arg);
        }
        break;
        case EV_CLOSURE_CB_SELF: {
            void (*evcb_selfcb)(struct event_callback *, void *) = evcb->evcb_cb_union.  
evcb_selfcb;
            EVBASE_RELEASE_LOCK(base, th_base_lock);
            evcb_selfcb(evcb, evcb->evcb_arg);//执行对应的回调函数
...
static void
event_queue_remove_active(struct event_base *base, struct event_callback *evcb)
{
    EVENT_BASE_ASSERT_LOCKED(base);
    if (EVUTIL_FAILURE_CHECK(!(evcb->evcb_flags & EVLIST_ACTIVE))) {
        event_errx(1, "%s: %p not on queue %x", __func__,
               evcb, EVLIST_ACTIVE);
        return;
    }
    DECR_EVENT_COUNT(base, evcb->evcb_flags);
    evcb->evcb_flags &= ~EVLIST_ACTIVE;
    base->event_count_active--;


    TAILQ_REMOVE(&base->activequeues[evcb->evcb_pri],
        evcb, evcb_active_next);
}//设置EV_PRESIST标志,触发事件会将激活队列对应的event移除,但是event还存在于全局event链表和fd链表
static inline void
event_signal_closure(struct event_base *base, struct event *ev)
{
    short ncalls;
    int should_break;


    /* Allows deletes to work */
    ncalls = ev->ev_ncalls;
    if (ncalls != 0)
        ev->ev_pncalls = &ncalls;
    EVBASE_RELEASE_LOCK(base, th_base_lock);
    while (ncalls) {
        ncalls--;
        ev->ev_ncalls = ncalls;
        if (ncalls == 0)
            ev->ev_pncalls = NULL;
        (*ev->ev_callback)(ev->ev_fd, ev->ev_res, ev->ev_arg);


        EVBASE_ACQUIRE_LOCK(base, th_base_lock);
        should_break = base->event_break;
        EVBASE_RELEASE_LOCK(base, th_base_lock);


        if (should_break) {
            if (ncalls != 0)
                ev->ev_pncalls = NULL;
            return;
        }
    }
}

你可能感兴趣的:(libevent学习)