相关UML:
CTimerEngine成员变量:
//状态变量
DWORD m_dwTimerSpace; //时间间隔,这个值后来应该是给了定时器线程
protected:
bool m_bService; //运行标志
DWORD m_dwTimePass; //经过时间
DWORD m_dwTimeLeave; //倒计时间
CTimerItemPtr m_TimerItemFree; //空闲数组
CTimerItemPtr m_TimerItemActive; //活动数组
这些是分析定时器线程函数需要了解的成员变量,其次是线程同步:
从代码中可以看出所有对:m_TimerItemActive; m_TimerItemFree;的操作都是在一个线程锁的保护之下的。
定时器线程:
通过CTimerThread绕一圈以后最终被循环执行的实际上是这个函数(m_dwTimerSpace控制最小时间):
//定时器通知
void CTimerEngine::OnTimerThreadSink()
{
//锁定资源
CThreadLockHandle LockHandle(&m_ThreadLock);
//倒计时间
if (m_dwTimeLeave==NO_TIME_LEFT)
{
ASSERT(m_TimerItemActive.GetCount()==0);
return;
}
//减少时间
ASSERT(m_dwTimeLeave>=m_dwTimerSpace);
m_dwTimeLeave-=m_dwTimerSpace;
m_dwTimePass+=m_dwTimerSpace;
//查询定时器
if (m_dwTimeLeave==0)
{
bool bKillTimer=false;
tagTimerItem * pTimerItem=NULL;
DWORD dwTimeLeave=NO_TIME_LEFT;
for (INT_PTR i=0;i<m_TimerItemActive.GetCount();)
{
//效验参数
pTimerItem=m_TimerItemActive[i];
ASSERT(pTimerItem!=NULL);
ASSERT(pTimerItem->dwTimeLeave>=m_dwTimePass);
//定时器处理
bKillTimer=false;
// 这一行做了--操作
pTimerItem->dwTimeLeave -= m_dwTimePass;
if (pTimerItem->dwTimeLeave==0L)
{
//发送通知
m_AttemperEvent.PostTimerEvent(pTimerItem->wTimerID,pTimerItem->wBindParam);
//设置次数
if (pTimerItem->dwRepeatTimes!=TIMER_REPEAT_TIMER)
{
ASSERT(pTimerItem->dwRepeatTimes>0);
if (pTimerItem->dwRepeatTimes==1L)
{
bKillTimer=true;
m_TimerItemActive.RemoveAt(i);
m_TimerItemFree.Add(pTimerItem);
}
else pTimerItem->dwRepeatTimes--;
}
//设置时间,从新开始倒计时
if (bKillTimer==false) pTimerItem->dwTimeLeave=pTimerItem->dwElapse;
}
//增加索引
if (bKillTimer==false)
{
i++;
dwTimeLeave=__min(dwTimeLeave,pTimerItem->dwTimeLeave);
ASSERT(dwTimeLeave%m_dwTimerSpace==0);
}
}
//设置响应
m_dwTimePass=0L;
m_dwTimeLeave=dwTimeLeave;
}
return;
}
CTimerEngine:
启动一个定时器线程,循环遍历定时器,如果发现满足出发条件的定时器就投递一个定时器消息到CQueueServiceEvent对象。