mangosd 之 IntervalTimer
在WorldRunnable的update函数中,会周期性更新各种信息,但是他们的更新频率不一定相同,mangos采用了数组的方式来实现了固定个数的定时器,看看代码:
class IntervalTimer
{
public:
IntervalTimer() : _interval(0), _current(0) {}
void Update(time_t diff) { _current += diff; if(_current<0) _current=0;}
bool Passed() { return _current >= _interval; }
void Reset() { if(_current >= _interval) _current -= _interval; }
void SetCurrent(time_t current) { _current = current; }
void SetInterval(time_t interval) { _interval = interval; }
time_t GetInterval() const { return _interval; }
time_t GetCurrent() const { return _current; }
private:
time_t _interval;
time_t _current;
};
IntervalTimer m_timers[WUPDATE_COUNT];
/// Timers for different object refresh rates
enum WorldTimers
{
WUPDATE_OBJECTS = 0,
WUPDATE_SESSIONS = 1,
WUPDATE_AUCTIONS = 2,
WUPDATE_WEATHERS = 3,
WUPDATE_UPTIME = 4,
WUPDATE_CORPSES = 5,
WUPDATE_EVENTS = 6,
WUPDATE_COUNT = 7
};
m_timers初始化:
m_timers[WUPDATE_OBJECTS].SetInterval(0);
m_timers[WUPDATE_SESSIONS].SetInterval(0);
m_timers[WUPDATE_WEATHERS].SetInterval(1000);
m_timers[WUPDATE_AUCTIONS].SetInterval(60000); //set auction update interval to 1 minute
m_timers[WUPDATE_UPTIME].SetInterval(10*60000); //Update "uptime" table every 10 minutes
m_timers[WUPDATE_CORPSES].SetInterval(20*60000); //erase corpses every 20 minutes
在IntervalTimer中保存的当前时间_current是一个相对值,即启动定时器后流失的时间,而这个时间的更新正是在update开始的时候通过调用IntervalTimer::Update(time_t diff)实现的。定时器的超时时间间隔通过SetInterval在初始化的时候设置,这样在WorldRunnable::Update中检查的时候,调用IntervalTimer::Passed就可以判定了,如果超时发生了,那么重置定时器(减掉超时的时间间隔),看看代码:
///
Handle session updates when the timer has passed
if (m_timers[WUPDATE_SESSIONS].Passed())
{
m_timers[WUPDATE_SESSIONS].Reset();
UpdateSessions(diff);
}
其实,这个实现是很简单,但是同时也在一定场合很好用的一种机制。如果你的定时器只有固定的几个,不会再多了,那么借鉴这个机制还是不错的。但是如果你的定时器是根据程序的进行,用户的行为动态改变的,这个机制就不满足需求了,就需要另外实现了,至于到底是基于list,heap,map,btree....就任你选择了。
阅读(1321) | 评论(0) | 转发(0) |