[libevent]event_base_loop()

int
event_base_loop(struct event_base *base, int flags)
{
	const struct eventop *evsel = base->evsel;//选择了epoll机制(如果之前选择了epoll)
	void *evbase = base->evbase;//epoll.c的epollop对象
	struct timeval tv;
	struct timeval *tv_p;
	int res, done;

	/* clear time cache */
	base->tv_cache.tv_sec = 0;//清除时间缓存,好让下面的gettime获得当前系统时间而不是获得缓存的时间

	if (base->sig.ev_signal_added)
		evsignal_base = base;//该变量也是一个全局的变量,赋值后关于信号的一些操作默认用到这个base
	done = 0;
	while (!done) {
		/* Terminate the loop if we have been asked to */
		if (base->event_gotterm) {//这两个是用来中断循环的标识
			base->event_gotterm = 0;
			break;
		}

		if (base->event_break) {
			base->event_break = 0;
			break;
		}

		timeout_correct(base, &tv);//如果使用了monotonic时钟类型则这个函数就没用了

		tv_p = &tv;
		if (!base->event_count_active && !(flags & EVLOOP_NONBLOCK)) {//如果没有就绪的事件,则获得接下来需要最小等待时间,用作epoll_wait的时间参数
			timeout_next(base, &tv_p);
		} else {
			/* 
			 * if we have active events, we just poll new events
			 * without waiting.
			 */
			evutil_timerclear(&tv);//有就绪事件则无需等待epoll_wait,时间设置为0
		}
		
		/* If we have no events, we just exit *///无事件注册了则退出循环
		if (!event_haveevents(base)) {
			event_debug(("%s: no events registered.", __func__));
			return (1);
		}

		/* update last old time */
		gettime(base, &base->event_tv);//如果使用了monotonic时钟,则这个也没什么意义

		/* clear time cache */
		base->tv_cache.tv_sec = 0;

		res = evsel->dispatch(base, evbase, tv_p);//内部使用epoll_wait()等待事件,不过仅仅处理读写事件,信号事件在evsignal_process()函数处理

		if (res == -1)
			return (-1);
		gettime(base, &base->tv_cache);//获得当前时间,更新缓存,缓存的作用是无需调用系统调用获得时间,省时

		timeout_process(base);//检查小根堆的事件是否到时,并进行删除过期事件和插入就绪链表的动作

		if (base->event_count_active) {//有就绪事件则调用事件注册的回调函数
			event_process_active(base);
			if (!base->event_count_active && (flags & EVLOOP_ONCE))
				done = 1;
		} else if (flags & EVLOOP_NONBLOCK)
			done = 1;
	}

	/* clear time cache */
	base->tv_cache.tv_sec = 0;

	event_debug(("%s: asked to terminate loop.", __func__));
	return (0);
}

你可能感兴趣的:(libevent源码分析)