基于升序链表的定时器

来源:互联网 发布:vb提取网页数据 编辑:程序博客网 时间:2024/06/02 09:42
#ifndef LST_TIMER
#define LST_TIMER


#include <time.h>


#define BUFFER_SIZE 64
class util_timer;
//用户数据结构:客户端地址、客户端的socket、socket文件描述符、读缓存和定时器
struct client_data
{
    sockaddr_in address;
    int sockfd;
    char buf[ BUFFER_SIZE ];
    util_timer* timer;
};


class util_timer
{
public:
    util_timer() : prev( NULL ), next( NULL ){}


public:
   time_t expire; //超时时间,使用绝对时间
   void (*cb_func)( client_data* );//任务回调
   client_data* user_data;//用户数据
   util_timer* prev;//双向链表,前一个定时器
   util_timer* next;//双向链表,后一个定时器
};
//定时器链表,它是一个升序、双向链表,且带有头结点和尾节点
class sort_timer_lst
{
public:
    sort_timer_lst() : head( NULL ), tail( NULL ) {}
    //释放内存   
   ~sort_timer_lst()
    {
        util_timer* tmp = head;
        while( tmp )
        {
            head = tmp->next;
            delete tmp;
            tmp = head;
        }
    }
//添加定时器
    void add_timer( util_timer* timer )
    {
        if( !timer )
        {
            return;
        }
        if( !head )
        {
            head = tail = timer;
            return; 
        }
//如果添加的定时器的时间比头结点的时间要短,直接将其作为头结点
        if( timer->expire < head->expire )
        {
            timer->next = head;
            head->prev = timer;
            head = timer;
            return;
        }
        add_timer( timer, head );
    }
//当某一个定时器发生变化时候,要调整对应定时器在链表中的位置
    void adjust_timer( util_timer* timer )
    {
        if( !timer )
        {
            return;
        }
        util_timer* tmp = timer->next;
//如果被调整的节点处于链表的尾部,或者新的超时值仍然小于其下一个定时器的超
//时值,则不需要调整

        if( !tmp || ( timer->expire < tmp->expire ) )
        {
            return;
        }
//如果定时器是头部,则对该定时器从链表中去除并重新插入
        if( timer == head )
        {
            head = head->next;
            head->prev = NULL;
            timer->next = NULL;
            add_timer( timer, head );
        }
        else
        {
//如果目标定时器不是链表的头结点,则将定时器从链表中去除,然后插入其原来的所在位置之后的部分链表
            timer->prev->next = timer->next;
            timer->next->prev = timer->prev;
            add_timer( timer, timer->next );
        }
    }
    void del_timer( util_timer* timer )
    {
        if( !timer )
        {
            return;
        }
        if( ( timer == head ) && ( timer == tail ) )
        {
            delete timer;
            head = NULL;
            tail = NULL;
            return;
        }
        if( timer == head )
        {
            head = head->next;
            head->prev = NULL;
            delete timer;
            return;
        }
        if( timer == tail )
        {
            tail = tail->prev;
            tail->next = NULL;
            delete timer;
            return;
        }
        timer->prev->next = timer->next;
        timer->next->prev = timer->prev;
        delete timer;
    }
//SIGARLM信号每一次被触发就在其信号处理函数(如果是使用统一定位源,则是主函数)中执

//行一次tick函数以处理链表上到期的任务

//tick相当于一个心搏函数,每隔一段时间执行一次,以处理到期的任务

    void tick()
    {
        if( !head )
        {
            return;
        }
        printf( "timer tick\n" );
        time_t cur = time( NULL );//获取系统当前时间
        util_timer* tmp = head;
//从头结点开始依次处理每一个定时器,直到遇到一个尚未到期的定时器,
//这就是定时器的核心逻辑
        while( tmp )
        {
//使用的是绝对时间,因此将超时值与当前系统时间进行比较
            if( cur < tmp->expire )
            {
                break;
            }
//调用定时器的回调函数
            tmp->cb_func( tmp->user_data );
//事件处理完毕之后就将其删除
            head = tmp->next;
            if( head )
            {
                head->prev = NULL;
            }
            delete tmp;
            tmp = head;
        }
    }


private:
    void add_timer( util_timer* timer, util_timer* lst_head )
    {
        util_timer* prev = lst_head;
        util_timer* tmp = prev->next;
        while( tmp )
        {
            if( timer->expire < tmp->expire )
            {
                prev->next = timer;
                timer->next = tmp;
                tmp->prev = timer;
                timer->prev = prev;
                break;
            }
            prev = tmp;
            tmp = tmp->next;
        }
        if( !tmp )
        {
            prev->next = timer;
            timer->prev = prev;
            timer->next = NULL;
            tail = timer;
        }
        
    }


private:
    util_timer* head;
    util_timer* tail;
};


#endif
0 0
原创粉丝点击