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]; };

浙公网安备 33010602011771号