很久以前就设计过定时器.所以基本都是抄现有的逻辑的.
- MyDogTimeCD 只需要设定cd,然后通过手动调用check来检查定时器是否达到.它不涉及到定时器事件,简单实用,适合一些依赖外部循环类使用.
- MyDogTimerMgr 注册定时器的时间及事件.毫秒级别的定时器,只通过一个列表存储.秒级别的,按秒/分/时,分成4个容器.秒级别的就是根据现实生活的时钟运行原理实现,每秒检测秒容器当前槽位是否触发,每一分钟就把分容器的定时器拉取到秒容器对应的槽位里,每一小时把时容器的定时器拉取到分容器对应的槽位里.每24小时就拉取第4个容器到对应的槽位.
MyDogTimeCD虽然没有事件注册,但是还是很实用的,具体哪里用到,可以看源码.
/// <summary>
/// timecd,默认秒单位
/// </summary>
class MyDogTimeCD {
uint32 endT;
uint16 life;//生命周期
public:
MyDogTimeCD(){}//配套init使用,所以可以不初始化
MyDogTimeCD(uint16 cd,bool sec = true);
void init(uint16 cd, bool sec = true);
inline bool check(uint32 nt,bool reset = true) {
if (nt >= endT) {
if (reset) {
endT = nt + life;
}
return true;
}
return false;
}
};
MyDogTimerMgr是一个高效,高精度的定时器管理器.前后端都合适,无须担心定时器多了,整个应用效率会下降.当然,并发的定时器,谁都扛不住.
先看看毫秒定时器
enum class EnumTimerResMs :int8
{
comeon,//重置
release,//释放定时器
};
typedef EnumTimerResMs(*TFuncMs)();
/// <summary>
/// 毫秒单元
/// </summary>
struct MyDogTimeCellMs {
friend class MyDogTimerMgr;
protected:
TFuncMs func;
uint16 life;//定时时间毫秒
uint32 endT;//结束时间戳秒
uint16 id;//max_uint16表明已经放入池
MyDogTimeCellMs() {}
inline void reset(uint32 currT) {
endT = currT + life;
}
inline bool check(uint32 currT) {
return func && (endT <= currT);
}
};
然后是秒定时器
enum class EnumTimerRes :int8
{
comeon,//继续或重置
stop,//暂停,继续后重新添加定时器
hangup,//挂起,继续后先根据剩余时间触发
release,//释放定时器
};
typedef EnumTimerRes (*TFunc)();
/// <summary>
/// 秒单元
/// </summary>
struct MyDogTimeCell
{
friend class MyDogTimerMgr;
protected:
TFunc func;
uint32 life;//定时时间秒
uint32 endT;//结束时间戳秒,挂起时表示剩余时间
int8 vecType;//所在容器 0 sec,1 min, 2 hour, 3 other
int8 vecPos;//具体位置
int8 stop_state;//停止状态 0 没有停止 1暂停 2挂起
MyDogTimeCell() {}
inline void reset(uint32 currT) {
if (stop_state == 2)
{
endT += currT;//因为挂起时表示剩余时间
}
else
{
endT = currT + life;
}
//stop_state = 0;//addCell的时候才赋值
}
inline bool check(uint32 currT) {
return func && (endT <= currT);
}
inline void onstop() {
stop_state = 1;
}
//计算剩余时间挂起
inline void onhangup(uint32 currT) {
endT = endT - currT;
stop_state = 2;
}
};
秒定时器的返回结果比毫秒定时器的丰富,多了个暂停和挂起.
MyDogTimerMgr的定义:
class MyDogTimerMgr
{
public:
MyDogTimerMgr();
~MyDogTimerMgr();
void onLoop(uint32 nt);
MyDogTimeCellMs* addTime(TFuncMs func, uint16 ms);//毫秒级别的定时器不能超过65s
void stopTime(MyDogTimeCellMs* tcms);
MyDogTimeCell* addTime(TFunc func, uint32 sec);//添加秒定时器
bool setTime(MyDogTimeCell* tc, EnumTimerRes tr, uint32 currT);//ontime前对time操作
protected:
MyDogTimeCell* createCell();
void addCell(MyDogTimeCell* cell);
void freeCell(MyDogTimeCell* cell);
void runOneSec(uint32 currT);//执行1秒
uint32 currSecT;
vector<MyDogTimeCellMs*> vecMs;//毫秒定时器
vector<MyDogTimeCellMs*> vecMsPool;//毫秒池
vector<MyDogTimeCell*> vecSecs[60];//秒容器
int8 secid;
vector<MyDogTimeCell*> vecMins[60];//分容器
int8 minid;
vector<MyDogTimeCell*> vecHours[24];//时容器
int8 hourid;
vector<MyDogTimeCell*> vecOthers;//剩余容器
vector<MyDogTimeCell*> vecPool;//池
vector<MyDogTimeCell*> vecTemp;
};
秒容器60个vector列表,分容器60个,时容器24个,具体实现看源码
当然是单线程的.....