目录
以下源码均基于libevent-2.0.21-stable。
在前文中,分析了小顶堆min_heap这一数据结构,并提到了Libevent就是利用min_heap来实现定时器的,接下来就分析一下min_heap是如何实现定时器的。
对于每一个需要监听的event,它都对应一个感兴趣的事件,当感兴趣的事件发生时,这个event就激活了。而实际上,往往都需要设置一个超时结构体timeval,这个超时结构体用来告诉内核“用多长时间去监听这个事件发生”,如果超过了这个时间event对应的感兴趣事件还没有发生,那么也会把这个event激活。为每一个event设置监听超时是很有必要的,因为不是所有event都需要永久监听的,当event的数目很多,就会有大量的超时结构体,定时器min_heap就是用来管理所有被监听的event的超时结构体的。
在libevent中,提供了common_timeout+min_heap的方式来进行超时管理,关于common_timeout会在后面文章中分析,这里只说一下min_heap。
min_heap的定义
每一个event_base都对应一个min_heap数据结构,其定义如下:
struct event_base {
......
/** Priority queue of events with timeouts. */
struct min_heap timeheap;
......
};
也就是说,event_base中的所有设置了超时的event都会放在event_base的timeheap这一成员中。
向min_heap中添加event
为event添加一个超时是通过event_add实现的,而在event_add内部实际上是event_add_internal函数,该函数共有三个传入参数,第一个参数是event指针,第二个参数是一个超时结构体timeval,第三个参数用于指明传入的超时结构体是否为绝对时间。如果传入的timeval非空,说明event是需要设置超时的,通过event_add_internal就可以将该event添加到min_heap中,如下所示:
static inline int
event_add_internal(struct event *ev, const struct timeval *tv,
int tv_is_absolute)
{
......
/*
* prepare for timeout insertion further below, if we get a
* failure on any step, we should not change any state.
*/
//如果event设置了超时,