时间轮定时器

#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

 

posted on 2015-02-07 10:11  kangbry  阅读(234)  评论(0)    收藏  举报

导航