libevent源码分析之时间管理和定时器

一、概述

libevent提供了高性能定时器的功能,方便执行延迟回调逻辑。

二、基本实现原理

在添加事件监听的时候,可以不指定fd和监听的事件,指定超时的时间,实现定时器功能。
定时器的底层实现包含两个部分:

  • 最小堆:按事件的超时时间构造,超时时间最早的在堆顶。
  • 通用超时队列:这个可以个性化设置每个队列的超时时间,添加事件时时间相同的放到同一个队列里,在最小堆里只添加一个队列首部的事件到最小堆。能避免大量事件都放到最小堆,导致最小堆添加、删除时性能变差的问题。

三、最小堆实现

最小堆的实现采用了典型的数组来维护,当数组元素满时,扩容数组,调整最小堆。
在这里插入图片描述

四、公共超时队列

1、用户可以自定义每个公共超时队列的超时时间,每个超时队列加入时时间的超时时间相同,这样保证了同一队列里的时间按加入队列时的时间超时。这样避免了在最小堆里维护大量的事件,只需在最小堆里加入一个超时事件即可。
2、公共超时队列的结构定义如下:

struct common_timeout_list {
    
    
struct event_list events; //事件列表
struct timeval duration; //duration表示加入到这个队列里时,都是duration的超时时间
struct event timeout_event; //每个common_timout_list,都会在超时最小堆里放一个超时事件,等timeout_event超时时,检查events里的哪些事件超时,并再往最小堆里加入一个超时事件。
struct event_base *base; //所属的event_base
};

3、具体的实现原理如下图:
在这里插入图片描述
每个队列是一个双向链表
在这里插入图片描述

五、定时器使用样例

	struct event timeout;
	struct timeval tv;
	struct event_base *base;
	int flags = 0; //0表示只执行一次,EV_PERSIST表示定时器超时后继续等待超时

	/* Initalize the event library */
	base = event_base_new();

	/* Initalize one event */
	event_assign(&timeout, base, -1, flags, timeout_cb, (void*) &timeout);

	evutil_timerclear(&tv);
	tv.tv_sec = 2;
	event_add(&timeout, &tv);

	evutil_gettimeofday(&lasttime, NULL);

	event_base_dispatch(base);

猜你喜欢

转载自blog.csdn.net/gamekit/article/details/113101356
今日推荐