使用epoll+时间堆实现高性能定时器

本文介绍了如何在Linux网络编程中使用epoll和时间堆创建高性能定时器。针对SIGALARM的低效和不便利,提出了一种基于时间堆的数据结构,实现了插入、删除和查找的高效操作。通过调整epoll_wait的超时时间,确保了最近触发的定时器能够及时执行。此外,还封装了tepoll_wait函数,优化了超时事件的处理方式。
摘要由CSDN通过智能技术生成

在开发Linux网络程序时,通常需要维护多个定时器,如维护客户端心跳时间、检查多个数据包的超时重传等。如果采用Linux的SIGALARM信号实现,则会带来较大的系统开销,且不便于管理。

本文在应用层实现了一个基于时间堆的高性能定时器,同时考虑到定时的粒度问题,由于通过alarm系统调用设置的SIGALARM信号只能以秒为单位触发,因此需要采用其它手段实现更细粒度的定时操作,当然,这里不考虑使用多线程+sleep的实现方法,理由性能太低。

通常的做法还有采用基于升序的时间链表,但升序时间链表的插入操作效率较低,需要遍历链表。因此本实现方案使用最小堆来维护多个定时器,插入O(logn)、删除O(1)、查找O(1)的效率较高。

首先是每个定时器的定义:

class heap_timer
{
public:
    heap_timer( int ms_delay )
    {
        gettimeofday( &expire, NULL );
        expire.tv_usec += ms_delay * 1000;
        if ( expire.tv_usec > 1000000 )
        {
            expire.tv_sec += expire.tv_usec / 1000000;
            expire.tv_usec %= 1000000;
        }
    }

public:
    struct timeval expire;
    void (*cb_func)( client_data* );
    client_data* user_data;
    ~heap_timer()
    {
        delete user_data;
    }
};

包括一个超时时间expire、超时回调函数cb_func以及一个user_data变量,user_data用于存储与定时器相关的用户数据,用户数据可以根据不同的应用场合进行修改,这里实现的是一个智能博物馆的网关,网关接收来自zigbee协调器的用户数据,并为每个用户维护一段等待时间T,在T到来之前,同一个用户的所有数据都存放到user_data的target_list中,当T到来时,根据target_list列表选择一个适当的target并发送到ip_address,同时删除定时器(有点扯远了=。=)。总之,要实现的功能就是给每个用户维护一个定时器,定时值到来时做一些操作。

class client_data
{
public:
    client_data(char *address):target_count(0)
    {
        strcpy(ip_address,address);
    }
private:
    char ip_address[32];
    target target_list[64];
    int target_count;
    ......
};
 

以下是时间堆的类定义,包括了一些基本的堆操作:插入、删除、扩容,还包括了定时器溢出时的操作函数tick()

class time_heap
{
public:
    time_heap( int cap  = 1) throw ( std::exception )
        : capacity( cap ), cu
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值