libevent代码阅读(11)——“hello-world.c”之 进入事件多路分发循环

前面的操作都完成之后,正式进入事件多路分发循环,在循环,Reactor框架等待事件的发生,然后寻找对应的事件处理器,然后调用对应的事件处理回调函数进行事件的处理,循环会一直运行,直到没有事件.

执行事件多路分发循环的函数是event_base_dispatch,它调用的其实是event_base_loop,它定义如下:

/*
 * 事件循环
 * 首先调用io事件多路分发器的事件监听函数,等待事件
 * 当有事件发生就依次处理之
 */
int
event_base_loop(struct event_base *base, int flags)
{
	// 获取后端支持的io复用机制(一般来说linux是epoll,对于windows则是iocp)
	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);

	// 一个event_base仅能运行一个事件循环
	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;
	}

	// 标记event_base已经开始运行
	base->running_loop = 1;

	// 清除event_base的系统时间缓存
	// 存储时间缓存的目的就是避免多次的系统调用
	clear_time_cache(base);

	// 设置信号事件的event_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;
		}
		// 校准系统时间
		timeout_correct(base, &tv);

		tv_p = &tv;

		// N_ACTIVE_CALLBACKS的作用是计算被激活的事件的数量
		if (!N_ACTIVE_CALLBACKS(base) && !(flags & EVLOOP_NONBLOCK))
		{
			/*
			 * 获取时间堆上堆顶元素的超时值,即io复用系统调用本次应该设置的超时值
			 */
			timeout_next(base, &tv_p);
		}
		else
		{
			/*
			 * if we have active events, we just poll new events
			 * without waiting.
			 */
			/*
			 * 如果有就绪事件尚未处理,则将io复用系统调用的超时事件设置为0
			 * 这样io复用系统调用就能直接返回,程序就能够立即处理就绪事件了
			 */
			evutil_timerclear(&tv);
		}

		/* If we have no events, we just exit */
		// 如果event_base中没有任何事件,则直接退出事件循环
		if (!event_haveevents(base) && !N_ACTIVE_CALLBACKS(base))
		{
			event_debug(("%s: no events registered.", __func__));
			retval = 1;
			goto done;
		}

		/* update last old time */
		// 更新系统事件
		gettime(base, &base->event_tv);

		// 清空时间缓存
		clear_time_cache(base);

		// 调用事件多路分发器的dispatch函数等待事件,将就绪的事件插入活动事件队列
		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))
		{
			// 调用event_process_active函数依次处理就绪的事件和io事件
			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_loop内部调用了event_process_active这个重要的函数:

// 执行事件已经被激活的事件处理器对应的回调函数
static int
event_process_active(struct event_base *base)
{
	/* Caller must hold th_base_lock */
	struct event_list *activeq = NULL;
	int i, c = 0;

	// 遍历每一个被激活的队列
	for (i = 0; i < base->nactivequeues; ++i)
	{
		// 如果该队列不为空
		if (TAILQ_FIRST(&base->activequeues[i]) != NULL)
		{
			// 设置运行时优先级
			base->event_running_priority = i;
			activeq = &base->activequeues[i];

			// 处理该队列内部的事件
			c = event_process_active_single_queue(base, activeq);

			if (c < 0)
			{
				base->event_running_priority = -1;
				return -1;
			}
			else if (c > 0)
				break; /* Processed a real event; do not
				 * consider lower-priority events */
			/* If we get here, all of the events we processed
			 * were internal.  Continue. */
		}
	}

	// 对于延时的调用,等上面的激活队列都被扫描完毕才轮到它执行
	event_process_deferred_callbacks(&base->defer_queue,&base->event_break);

	// 设置运行时优先级
	base->event_running_priority = -1;
	return c;
}

event_process_active_single_queue用于处理单个队列当中的事件处理器

/*
 * 处理单个激活队列内部的所有事件
 * 返回有多少个非内部事件被处理
 */
static int
event_process_active_single_queue(struct event_base *base,
		struct event_list *activeq)
{
	struct event *ev;

	// 非内部事件的数量
	int count = 0;

	EVUTIL_ASSERT(activeq != NULL);

	// 遍历事件处理器队列中的每一个事件处理器
	for (ev = TAILQ_FIRST(activeq); ev; ev = TAILQ_FIRST(activeq))
	{
		// 如果是永久事件,那么将它从激活事件队列中移除
		// 否则,将他从所有的队列中删除
		if (ev->ev_events & EV_PERSIST)
			event_queue_remove(base, ev, EVLIST_ACTIVE);
		else
			event_del_internal(ev);

		// 非内部事件
		if (!(ev->ev_flags & EVLIST_INTERNAL))
			++count;

		event_debug((
				"event_process_active: event: %p, %s%scall %p",
				ev,
				ev->ev_res & EV_READ ? "EV_READ " : " ",
						ev->ev_res & EV_WRITE ? "EV_WRITE " : " ",
								ev->ev_callback));

#ifndef _EVENT_DISABLE_THREAD_SUPPORT
		base->current_event = ev;
		base->current_event_waiters = 0;
#endif

		// ev_closure指定event_base执行事件处理器的回调函数时候的行为
		switch (ev->ev_closure)
		{
		case EV_CLOSURE_SIGNAL:
			// 信号事件处理
			event_signal_closure(base, ev);
			break;
		case EV_CLOSURE_PERSIST:
			// 永久性事件处理
			// 其实就是定时事件(定时器之类的)
			event_persist_closure(base, ev);
			break;
		default:
		case EV_CLOSURE_NONE:
			EVBASE_RELEASE_LOCK(base, th_base_lock);

			// 执行事件处理器的回调函数
			(*ev->ev_callback)( ev->ev_fd, ev->ev_res, ev->ev_arg);

			break;
		}

		EVBASE_ACQUIRE_LOCK(base, th_base_lock);
#ifndef _EVENT_DISABLE_THREAD_SUPPORT
		base->current_event = NULL;
		if (base->current_event_waiters)
		{
			base->current_event_waiters = 0;
			EVTHREAD_COND_BROADCAST(base->current_event_cond);
		}
#endif

		// 如果event_base循环中断了,那么就直接返回
		if (base->event_break)
			return -1;

		// 如果event_base跳过本次循环,那么剩余的事件也不再处理
		if (base->event_continue)
			break;
	}
	return count;
}
event_process_active_single_queue的内部分别调用了event_signal_closure和event_persist_closure,前者专门处理信号事件,后者处理永久性事件(即定时事件):

/*
 * 信号处理
 */
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);

	// 执行ncalls次回调函数
	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;
		}
	}
}

/*
 * 专门处理永久性事件(即定时器事件)
 */
static inline void
event_persist_closure(struct event_base *base, struct event *ev)
{
	// Define our callback, we use this to store our callback before it's executed
	void (*evcb_callback)(evutil_socket_t, short, void *);

	// Other fields of *ev that must be stored before executing
	evutil_socket_t evcb_fd;
	short evcb_res;
	void *evcb_arg;

	/* reschedule the persistent event if we have a timeout. */
	// 重新调度这个定时器事件,如果这个事件有超时设置
	if (ev->ev_io_timeout.tv_sec || ev->ev_io_timeout.tv_usec) {
		/* If there was a timeout, we want it to run at an interval of
		 * ev_io_timeout after the last time it was _scheduled_ for,
		 * not ev_io_timeout after _now_.  If it fired for another
		 * reason, though, the timeout ought to start ticking _now_. */

		struct timeval
		run_at, 		// 在某个时刻运行
		relative_to, 	// 相对于超时时间
		delay, 			// 延迟时间
		now;			// 当前时间

		ev_uint32_t usec_mask = 0;
		EVUTIL_ASSERT(is_same_common_timeout(&ev->ev_timeout,
				&ev->ev_io_timeout));

		// 获取当前时间
		gettime(base, &now);

		// 判断ev->ev_timeout是不是event_base的公共超时时间
		if (is_common_timeout(&ev->ev_timeout, base))
		{
			delay = ev->ev_io_timeout;
			usec_mask = delay.tv_usec & ~MICROSECONDS_MASK;
			delay.tv_usec &= MICROSECONDS_MASK;
			if (ev->ev_res & EV_TIMEOUT)
			{
				relative_to = ev->ev_timeout;
				relative_to.tv_usec &= MICROSECONDS_MASK;
			}
			else
			{
				relative_to = now;
			}
		}
		else
		{
			delay = ev->ev_io_timeout;
			if (ev->ev_res & EV_TIMEOUT)
			{
				relative_to = ev->ev_timeout;
			}
			else
			{
				relative_to = now;
			}
		}

		// 重新添加定时器
		evutil_timeradd(&relative_to, &delay, &run_at);

		if (evutil_timercmp(&run_at, &now, <))
		{
			/* Looks like we missed at least one invocation due to
			 * a clock jump, not running the event loop for a
			 * while, really slow callbacks, or
			 * something. Reschedule relative to now.
			 */
			// 重新添加定时器
			evutil_timeradd(&now, &delay, &run_at);
		}

		run_at.tv_usec |= usec_mask;

		// 事件添加
		event_add_internal(ev, &run_at, 1);
	}

	// Save our callback before we release the lock
	evcb_callback = ev->ev_callback;
	evcb_fd = ev->ev_fd;
	evcb_res = ev->ev_res;
	evcb_arg = ev->ev_arg;

	// Release the lock
	EVBASE_RELEASE_LOCK(base, th_base_lock);

	// Execute the callback
	// 执行回调函数
	(evcb_callback)(evcb_fd, evcb_res, evcb_arg);
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值