linux event 队列,关于libevent的定时器

对于定时器事件,Libevent采用两种方法处理定时器:

1、定时器尾队列

2、时间堆

在event结构体中,定义了联合体类型ev_timeout_pos来指明定时器的位置

//仅用于定时事件处理器:当为通过定时器时,ev_next_with_common_timeout指向定时器队列中的位置

//当为其它定时器时,min_heap_idx为指向时间堆中的索引

union {

TAILQ_ENTRY(event) ev_next_with_common_timeout;

int min_heap_idx;

} ev_timeout_pos;

开发者认为有时候使用简单的链表(通用定时器)来管理定时器将具有更高的效率。如下所述:

当需要获取多个具有同一超时值的定时器时,定时器链表比时间堆效率更高,此处个人理解为:若超时时间相同,在定时器链表中,可以通过顺序遍历的方法获取超时的定时器,而采用时间堆的话,每获取一个定时器需要维护堆,时间复杂度为nlogn。

一个定时器是否是通用定时器取决于其超时值(超时值由具体超时值、幻数5以及定时器索引组成),具体由is_common_timeout函数决定:

/* Common timeouts are special timeouts that are handled as queues rather than

* in the minheap. This is more efficient than the minheap if we happen to

* know that we're going to get several thousands of timeout events all with

* the same timeout value.

*

* Since all our timeout handling code assumes timevals can be copied,

* assigned, etc, we can't use "magic pointer" to encode these common

* timeouts. Searching through a list to see if every timeout is common could

* also get inefficient. Instead, we take advantage of the fact that tv_usec

* is 32 bits long, but only uses 20 of those bits (since it can never be over

* 999999.) We use the top bits to encode 4 bites of magic number, and 8 bits

* of index into the event_base's aray of common timeouts.

*/

#define MICROSECONDS_MASK    COMMON_TIMEOUT_MICROSECONDS_MASK

#define COMMON_TIMEOUT_IDX_MASK 0x0ff00000

#define COMMON_TIMEOUT_IDX_SHIFT 20

#define COMMON_TIMEOUT_MASK  0xf0000000

#define COMMON_TIMEOUT_MAGIC  0x50000000

#define COMMON_TIMEOUT_IDX(tv) \

(((tv)->tv_usec & COMMON_TIMEOUT_IDX_MASK)>>COMMON_TIMEOUT_IDX_SHIFT)

/** Return true iff if 'tv' is a common timeout in 'base' */

static inline int

is_common_timeout(const struct timeval *tv,

const struct event_base *base)

{

int idx;

if ((tv->tv_usec & COMMON_TIMEOUT_MASK) != COMMON_TIMEOUT_MAGIC)

return 0;

idx = COMMON_TIMEOUT_IDX(tv);

return idx < base->n_common_timeouts;

}

32位定时值tv->tv_usec高四位为幻数,该定时器的幻数不等于0101b时,定时器是时间堆定时器;

idx = COMMON_TIMEOUT_IDX取出定时器的20-27位(由于定时器不超过999999,只用了0-19位,因此20-31位可以用于铺助功能,这个是个编程技巧),判断idx < Reactor对象中的n_common_timeouts,该变量保存了当前Reactor对象中通用定时器队列的长度,若idx在长度范围内,则为通用定时器,否则为时间堆定时器。

0b1331709591d260c1c78e86d0c51c18.png

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值