实现了一个简单的timer
2009-04-01 22:59
246 查看
对于游戏编程来说,timer是绝对不陌生的,不过以前一直使用一些库提供的timer,像sdl的timer,windows api提供的timer,这段时间突然觉得像这种东西还是在自己的游戏引擎里面实现一个,作为基本类库使用。
首先参考了一下linux的timer机制,详细见 http://www.linuxforum.net/forum/showthreaded.php?Cat=&Board=driver&Number=385224&page=0&view=collapsed&sb=5&o=all&vc=1
不过我实现的跟这个还是有点不一样的。
主要思想就是采用一个timer wheel,假设有一个timer的循环队列,队列上面的每个对象(我们叫做slot)是一个timer的list,现在我们处理到了第m轮第n个slot上面,这时候注册了一个timer,这个timer的间隔为interval毫秒,那么这个timer就应该放到第 n + interval / timer_interval (timer_interval为定时器的精度时间)的slot上面,然后挂在到该slot对应的list末尾,因为我们的环有长度,所以如果注册的timer interval时间很长,interval / timer_interval + n可能超出了wheel的长度,不过由于我们是一个环状结构,所以我们这个timer会在第 m + interval % timer_interval轮之后运行,同时是放到 (n + interval / timer_interval) % max_slotnum这个slot上面。
注册完成以后,当我们的处理到相应的slot的上面的时候,我们会一次的从list上面取出timer,然后现判断是否该timer是在该轮运行,不是则不处理,是则处理。如果碰到interval为0的timer,则会一直处理,知道该timer自己删除自己。
另外,由于我们的定时器有一个最小精度,所以除了interval为0的以外,其他的小于timer_interval的时间,我们全认为是timer_interval。
这个timer实现的非常简单,而且只能保证精度为timer_interval(一般也就是30ms),不过对于我来说,已经够了。
下面帖代码。
首先参考了一下linux的timer机制,详细见 http://www.linuxforum.net/forum/showthreaded.php?Cat=&Board=driver&Number=385224&page=0&view=collapsed&sb=5&o=all&vc=1
不过我实现的跟这个还是有点不一样的。
主要思想就是采用一个timer wheel,假设有一个timer的循环队列,队列上面的每个对象(我们叫做slot)是一个timer的list,现在我们处理到了第m轮第n个slot上面,这时候注册了一个timer,这个timer的间隔为interval毫秒,那么这个timer就应该放到第 n + interval / timer_interval (timer_interval为定时器的精度时间)的slot上面,然后挂在到该slot对应的list末尾,因为我们的环有长度,所以如果注册的timer interval时间很长,interval / timer_interval + n可能超出了wheel的长度,不过由于我们是一个环状结构,所以我们这个timer会在第 m + interval % timer_interval轮之后运行,同时是放到 (n + interval / timer_interval) % max_slotnum这个slot上面。
注册完成以后,当我们的处理到相应的slot的上面的时候,我们会一次的从list上面取出timer,然后现判断是否该timer是在该轮运行,不是则不处理,是则处理。如果碰到interval为0的timer,则会一直处理,知道该timer自己删除自己。
另外,由于我们的定时器有一个最小精度,所以除了interval为0的以外,其他的小于timer_interval的时间,我们全认为是timer_interval。
这个timer实现的非常简单,而且只能保证精度为timer_interval(一般也就是30ms),不过对于我来说,已经够了。
下面帖代码。
/**********************************************/ //BaseType.h /**********************************************/ #pragma once typedef char int8; typedef short int16; typedef int int32; typedef long long int64; typedef unsigned char uint8; typedef unsigned short uint16; typedef unsigned int uint32; typedef unsigned long long uint64; /**********************************************/ //CTimer.h /**********************************************/ #pragma once #include "BaseType.h" #include <list> class CTimer { friend class CTimerMgr; public: CTimer(); ~CTimer(); virtual void OnTimer(); private: uint32 m_uInterval; //timer的间隔时间 uint32 m_uRing; //第几轮运行 std::list<CTimer*>* m_pTimerList; //在当前哪个mgr list上面 std::list<CTimer*>::iterator m_itInList; //在timer list上面对应的iteratoro }; /**********************************************/ //CTimer.cpp /**********************************************/ #include "CTimer.h" #include <list> using namespace std; CTimer::CTimer() : m_pTimerList(NULL), m_uInterval(0), m_uRing(0) { } CTimer::~CTimer() { if(m_pTimerList) m_pTimerList->erase(m_itInList); } void CTimer::OnTimer() { } /**********************************************/ //CTimerMgr.h /**********************************************/ #pragma once #include "BaseType.h" #include <vector> #include <list> class CTimer; class CTimerMgr { friend class CTimer; public: CTimerMgr(uint32 uInterval, uint32 uSlotNum); ~CTimerMgr(); void RegisterTimer(CTimer* pTimer, uint32 uInterval); void UnRegisterTimer(CTimer* pTimer); void OnTimer(); private: std::vector<std::list<CTimer*>* > m_vecTimerContainer; uint32 m_uInterval; uint32 m_uSlotNum; uint32 m_uRing; uint32 m_uCurSlot; }; /**********************************************/ //CTimerMgr.cpp /**********************************************/ #include "CTimerMgr.h" #include "CTimer.h" #include <vector> #include <list> #include <assert.h> using namespace std; CTimerMgr::CTimerMgr(uint32 uInterval, uint32 uSlotNum) : m_uInterval(uInterval), m_uSlotNum(uSlotNum), m_uRing(0), m_uCurSlot(0) { for(int i = 0; i < uSlotNum; i++) { list<CTimer*>* pTimerList = new list<CTimer*>; m_vecTimerContainer.push_back(pTimerList); } } CTimerMgr::~CTimerMgr() { for(int i = 0; i < m_uSlotNum; i++) { list<CTimer*>* pTimerList = m_vecTimerContainer[i]; while(pTimerList->empty()) { CTimer* pTimer = pTimerList->front(); delete pTimer; } delete pTimerList; } m_vecTimerContainer.clear(); } void CTimerMgr::RegisterTimer(CTimer* pTimer, uint32 uInterval) { //除了0以外,timer的最小精度为m_uInterval if(uInterval != 0 && uInterval < m_uInterval) uInterval = m_uInterval; uint32 uSlot = m_uCurSlot + uInterval / m_uInterval; if(uSlot >= m_uSlotNum) { pTimer->m_uRing = m_uRing + uSlot / m_uSlotNum; uSlot = uSlot % m_uSlotNum; } else { pTimer->m_uRing = m_uRing; } list<CTimer*>* pTimerList = m_vecTimerContainer[uSlot]; pTimer->m_pTimerList = pTimerList; pTimer->m_uInterval = uInterval; pTimerList->push_back(pTimer); pTimer->m_itInList = --pTimerList->end(); } void CTimerMgr::UnRegisterTimer(CTimer* pTimer) { if(!pTimer) return; list<CTimer*>* pTimerList = pTimer->m_pTimerList; pTimerList->erase(pTimer->m_itInList); pTimer->m_pTimerList = NULL; delete pTimer; } void CTimerMgr::OnTimer() { list<CTimer*>* pTimerList = m_vecTimerContainer[m_uCurSlot]; list<CTimer*> NextTimerList; while(!pTimerList->empty()) { CTimer* pTimer = pTimerList->front(); if(pTimer->m_uRing != m_uRing) { NextTimerList.push_back(pTimer); pTimerList->pop_front(); continue; } if(pTimer->m_uInterval == 0) { //不停调用,直到删除自己 while(!pTimer->m_pTimerList) { pTimer->OnTimer(); } continue; } else { pTimer->OnTimer(); //如果timer删除了 if(!pTimer->m_pTimerList) continue; uint32 uSlot = pTimer->m_uInterval / m_uInterval; assert(uSlot > 0); uSlot += m_uCurSlot; if(uSlot >= m_uSlotNum) { pTimer->m_uRing = m_uRing + uSlot / m_uSlotNum; uSlot = uSlot % m_uSlotNum; } else { pTimer->m_uRing = m_uRing; } list<CTimer*>* pNewTimerList = m_vecTimerContainer[uSlot]; pTimerList->pop_front(); pNewTimerList->push_back(pTimer); pTimer->m_pTimerList = pNewTimerList; pTimer->m_itInList = --pNewTimerList->end(); } } pTimerList->swap(NextTimerList); //移动到下一个slot,如果到了最后,则开始下一轮 ++m_uCurSlot; if(m_uCurSlot == m_uSlotNum) { m_uCurSlot = 0; ++m_uRing; } }
相关文章推荐
- 简单实现一个Unity3d的Timer
- 实现了一个简单的timer
- linux内核定时器--------一个简单的timer的实现
- GWT 2.0 UiBinder 实现一个简单的分页.实现简单的CRUD.
- 一个简单的RMI会话实现
- 一个简单的jQuery插件ajaxfileupload实现ajax上传文件例子
- 用原生JS实现一个简单的计时器demo
- 实现一个简单的shared_ptr
- 01 TCP Socket 编程_一个简单的服务端程序和客户端程序实现
- Java实训——创建一个窗体程序,实现简单的数学加、减法测试。
- 实现一个最简单的boot
- 用servlet实现一个简单的购物车程序
- linux设备驱动第三篇:如何实现一个简单的字符设备驱动
- 聊聊高并发(十五)实现一个简单的读-写锁(共享-排他锁)
- 一个简单的协程实现
- 一个简单木马程序的实现
- 实现一个简单的文件上传进度条
- 一个简单的自定义ClassLoader的实现
- 使用Python实现一个简单的项目监控
- 实现一个简单的 页面划入效果