libevent 源码分析event_base_dispatch,event_base_loop,event_base

 

接口:event_base_dispatch

/**
   Event dispatching loop 事件分配循环

  This loop will run the event base until either there are no more pending or
  active, or until something calls event_base_loopbreak() or
  event_base_loopexit().
  这个循环将会运行event base,知道没有等待的或者活动的事件,或者其它的调用了event_base_loopbreak()或event_base_loopexit().
  @param base the event_base structure returned by event_base_new() or
     event_base_new_with_config() event_base_new() 或者 event_base_new_with_config() 返回的event_base对象
  @return 0 if successful, -1 if an error occurred, or 1 if we exited because
     no events were pending or active. 成功返回0, 错误返回-1, 或者1(当没有等待的或者活动事件时退出,会返回1)
  @see event_base_loop()
 */
EVENT2_EXPORT_SYMBOL
int event_base_dispatch(struct event_base *base);
int
event_base_dispatch(struct event_base *event_base)
{
    return (event_base_loop(event_base, 0));
}

 

跟踪event_base_loop接口

/**
  Wait for events to become active, and run their callbacks.
  等待events 变成活动的,并运行对应的回调函数。
  This is a more flexible version of event_base_dispatch().
  这是一个更为灵活的event_base_dispatch()
  By default, this loop will run the event base until either there are no more
  pending or active events, or until something calls event_base_loopbreak() or
  event_base_loopexit().  You can override this behavior with the 'flags'
  argument.
  默认的,这个循环会运行event base,知道没有等待的或者活动的事件, 或者知道其它的调用了event_base_loopbreak() 或者 event_base_loopexit().
通过‘flags’参数,你可以从在这个行为。 @param eb the event_base structure returned by event_base_new() or event_base_new_with_config() event_base_new() 或者event_base_new_with_config() 创建event_base对象 @param flags any combination of EVLOOP_ONCE | 其它的和EVLOOP_NONBLOCK EVLOOP_ONCE | EVLOOP_NONBLOCK 组合 @return 0 if successful, -1 if an error occurred, or 1 if we exited because no events were pending or active. 成功返回0,错误返回-1,或者1(当没有等待的或者活动的事件时,退出) @see event_base_loopexit(), event_base_dispatch(), EVLOOP_ONCE, EVLOOP_NONBLOCK
*/ EVENT2_EXPORT_SYMBOL int event_base_loop(struct event_base *eb, int flags);
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;
    struct evwatch_prepare_cb_info prepare_info;
    struct evwatch_check_cb_info check_info;
    struct evwatch *watcher;

    /* Grab the lock.  We will release it inside evsel.dispatch, and again
     * as we invoke watchers and user callbacks. */
  // 锁。将会在evsel.dispatch内部释放它,在调用观察者和用户回调时也会再次释放
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); 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); /* Invoke prepare watchers before polling for events */ prepare_info.timeout = tv_p; TAILQ_FOREACH(watcher, &base->watchers[EVWATCH_PREPARE], next) { EVBASE_RELEASE_LOCK(base, th_base_lock); (*watcher->callback.prepare)(watcher, &prepare_info, watcher->arg); EVBASE_ACQUIRE_LOCK(base, th_base_lock); } 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); /* Invoke check watchers after polling for events, and before * processing them */ TAILQ_FOREACH(watcher, &base->watchers[EVWATCH_CHECK], next) { EVBASE_RELEASE_LOCK(base, th_base_lock); (*watcher->callback.check)(watcher, &check_info, watcher->arg); EVBASE_ACQUIRE_LOCK(base, th_base_lock); } timeout_process(base); 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); }

 

看下返回的event_base

struct event_base {
    /** Function pointers and other data to describe this event_base's
     * backend. */ 函数指针
    const struct eventop *evsel;
    /** Pointer to backend-specific data. */ 指向指定后端数据
    void *evbase;

    /** List of changes to tell backend about at next dispatch.  Only used
     * by the O(1) backends. */ 变动列表,用来告诉后端下一个被分派的。
    struct event_changelist changelist;

    /** Function pointers used to describe the backend that this event_base
     * uses for signals */ 
    const struct eventop *evsigsel;
    /** Data to implement the common signal handler code. */ 实现通用信号处理的代码
    struct evsig_info sig;

    /** Number of virtual events */
    int virtual_event_count;
    /** Maximum number of virtual events active */
    int virtual_event_count_max;
    /** Number of total events added to this event_base */
    int event_count;
    /** Maximum number of total events added to this event_base */
    int event_count_max;
    /** Number of total events active in this event_base */
    int event_count_active;
    /** Maximum number of total events active in this event_base */
    int event_count_active_max;

    /** Set if we should terminate the loop once we're done processing
     * events. */
    int event_gotterm;
    /** Set if we should terminate the loop immediately */
    int event_break;
    /** Set if we should start a new instance of the loop immediately. */
    int event_continue;

    /** The currently running priority of events */
    int event_running_priority;

    /** Set if we're running the event_base_loop function, to prevent
     * reentrant invocation. */
    int running_loop;

    /** Set to the number of deferred_cbs we've made 'active' in the
     * loop.  This is a hack to prevent starvation; it would be smarter
     * to just use event_config_set_max_dispatch_interval's max_callbacks
     * feature */
    int n_deferreds_queued;

    /* Active event management. */
    /** An array of nactivequeues queues for active event_callbacks (ones
     * that have triggered, and whose callbacks need to be called).  Low
     * priority numbers are more important, and stall higher ones.
     */
    struct evcallback_list *activequeues;
    /** The length of the activequeues array */
    int nactivequeues;
    /** A list of event_callbacks that should become active the next time
     * we process events, but not this time. */
    struct evcallback_list active_later_queue;

    /* common timeout logic */

    /** An array of common_timeout_list* for all of the common timeout
     * values we know. */
    struct common_timeout_list **common_timeout_queues;
    /** The number of entries used in common_timeout_queues */
    int n_common_timeouts;
    /** The total size of common_timeout_queues. */
    int n_common_timeouts_allocated;

    /** Mapping from file descriptors to enabled (added) events */
    struct event_io_map io;

    /** Mapping from signal numbers to enabled (added) events. */
    struct event_signal_map sigmap;

    /** Priority queue of events with timeouts. */
    struct min_heap timeheap;

    /** Stored timeval: used to avoid calling gettimeofday/clock_gettime
     * too often. */
    struct timeval tv_cache;

    struct evutil_monotonic_timer monotonic_timer;

    /** Difference between internal time (maybe from clock_gettime) and
     * gettimeofday. */
    struct timeval tv_clock_diff;
    /** Second in which we last updated tv_clock_diff, in monotonic time. */
    time_t last_updated_clock_diff;

#ifndef EVENT__DISABLE_THREAD_SUPPORT
    /* threading support */
    /** The thread currently running the event_loop for this base */
    unsigned long th_owner_id;
    /** A lock to prevent conflicting accesses to this event_base */
    void *th_base_lock;
    /** A condition that gets signalled when we're done processing an
     * event with waiters on it. */
    void *current_event_cond;
    /** Number of threads blocking on current_event_cond. */
    int current_event_waiters;
#endif
    /** The event whose callback is executing right now */
    struct event_callback *current_event;

#ifdef _WIN32
    /** IOCP support structure, if IOCP is enabled. */
    struct event_iocp_port *iocp;
#endif

    /** Flags that this base was configured with */
    enum event_base_config_flag flags;

    struct timeval max_dispatch_time;
    int max_dispatch_callbacks;
    int limit_callbacks_after_prio;

    /* Notify main thread to wake up break, etc. */
    /** True if the base already has a pending notify, and we don't need
     * to add any more. */
    int is_notify_pending;
    /** A socketpair used by some th_notify functions to wake up the main
     * thread. */
    evutil_socket_t th_notify_fd[2];
    /** An event used by some th_notify functions to wake up the main
     * thread. */
    struct event th_notify;
    /** A function used to wake up the main thread from another thread. */
    int (*th_notify_fn)(struct event_base *base);

    /** Saved seed for weak random number generator. Some backends use
     * this to produce fairness among sockets. Protected by th_base_lock. */
    struct evutil_weakrand_state weakrand_seed;

    /** List of event_onces that have not yet fired. */
    LIST_HEAD(once_event_list, event_once) once_events;

    /** "Prepare" and "check" watchers. */
    struct evwatch_list watchers[EVWATCH_MAX];
};

 

posted @ 2020-06-15 10:19  N_zero  阅读(1210)  评论(0)    收藏  举报