#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信号每一次被触发就在其信号处理函数(如果是使用统一定位源,则是主函数)中执
{
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
#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