时间轮定时器
#ifndef __timer__
#define __timer__
#pragma once
#include "thread.h"
#include "mutex_lock.h"
#include "ring_buffer.h"
#include "object_pool.h"
#include "comm.h"
#include <map>
using namespace std;
#define TICK_SPACE 1 //ms
#define sbits 6
#define ebits 8
#define sbitsize ( 1 << sbits )
#define ebitsize ( 1 << ebits )
#define sMask ( sbitsize- 1)
#define eMask ( ebitsize -1)
#define WHEEL_COUNT 5
#define WHEEL0_MAX ( 1 << ebits )
#define WHEEL1_MAX ( 1 << (sbits + ebits) )
#define WHEEL2_MAX ( 1 << (sbits + 2 * ebits) )
#define WHEEL3_MAX ( 1 << (sbits + 3 * ebits) )
#define WHEEL4_MAX 0xfffffff
#define WHEEL(wheel,n) (wheel##n)
/*
定义5个齿轮 每个齿轮的小齿数为 256 64 64 64 64 表示的数据范围为 0 ~ 2^8 ,2^8 ~ 2^14, 2^14 ~ 2^20, 2^20 ~ 2^26, 2^26 ~ 2^32
定义最小齿表示时间长度为tick 所以能到表示的范围为 0 ~ 2^32 * tick
算法
@ set_timer 通过取余hash将结点插入到不同轮子的不同齿上
@ kill_timer 先算hash 然后删除指定齿轮上的结点
@ check_timer 间隔/tick计算出需要遍历多少个小齿 遍历最小齿轮的小齿上是否有结点 有则callback 删除结点 小齿轮遍历完 将下一级齿轮小齿加1 并将该齿上的结点加入小齿中
@ cascade_timer 小齿轮转满后 大齿轮的齿进一格 小齿轮归零 (原理类似水表) 即将大齿轮这齿上的链表加入到下一级齿轮的对应不同小齿中
*/
//时间齿 每个时间齿上是一条双向链表
#pragma pack(push,1)
struct timer_info
{
_uint32 timerid; //定时器id
int interval; //定时间隔
_uint32 repeat; //重复次数
void* param; //参数
timer_info()
{
timerid = 0;
interval = 0;
repeat = 1;
param = 0;
}
};
#pragma pack(pop)
typedef void (* timer_sink)(timer_info& info,_uint32 repeat);
#pragma pack(push,1)
struct timer_asyn_data{
timer_sink sink;
timer_info info;
_uint32 repeated;
};
#pragma pack(pop)
#pragma pack(push,1)
struct spoke_node
{
spoke_node* next; //前一个结点
spoke_node* prev; //后一个结点
_uint32 expires; //过期时间
_uint32 repeated; //已经执行次数
timer_sink sink; //回调
timer_info info; //定时器信息
spoke_node()
{
sink = 0;
next = 0;
prev = 0;
expires = 0;
repeated = 0;
}
//将自己从链表中删除
void delete_self()
{
if(prev && next)
{
prev->next = next;
next->prev = prev;
}
}
};
#pragma pack(pop)
//时间轮 每个时间轮上是一个时间齿轮数组
class timer_wheel
{
public:
timer_wheel(int size);
~timer_wheel();
//初始化某个小齿
void init_spoke(int index) { m_list[index].next = &m_list[index]; m_list[index].prev = m_list[index].next; }
//转动到某个小齿
void set_index(int index) { m_index = index; }
//获取小齿index
int get_index() const { return m_index; }
//获取某个小齿指针
spoke_node* get_spoke() const { return get_spoke(m_index); }
spoke_node* get_spoke(int index) const { return ((index >= 0 && index < m_size) ? &m_list[index] : NULL);}
//删除某个小齿的结点
void del_node(spoke_node* node);
//插入结点到某个小齿链表尾巴
void insert_node(int index,spoke_node* node);
private:
spoke_node* m_list;
int m_index; //在第几个齿上 默认为0
int m_size; //轮上齿的个数
};
//定时器
class c_timer:public c_thread
{
public:
c_timer();
~c_timer();
bool set_timer(timer_sink sink,timer_info& info);
bool kill_timer(_uint32 timerid);
void cascade_timer(timer_wheel* wheel);
bool kill_all_timer();
void on_timer();
virtual void run();
private:
bool add_ansy_data(timer_sink sink,timer_info& info,_uint32 repeated);
void on_ansy_timer();
private:
mutex_lock m_lock;
ring_buffer m_asyn_data;
map<_uint32,spoke_node*> m_timer_list; //timerid --> node
object_pool<spoke_node> m_node_pool; //
timer_wheel** m_wheels; //5个轮子
_uint32 m_timer_idx; //timerid
_uint32 m_last_check_time; //上一次tick时间
_uint32 m_total_tick_time; //tick时间
};
#endif
本博客内容均来自网络,如有雷同,是我抄袭!
浙公网安备 33010602011771号