定时器Timer的实现

时间:2022-07-18 19:13:43
定时器Timer的实现

        定时器在实际项目中会用的比较平凡。因此,本文首先介绍定时器Timer的windows版本,跨平台的定时器将在下一篇文章中介绍。它们的源代码均用C++编写。源代码详见:https://github.com/duankai/Timer

1.      定时器结构体类型

typedef struct TIMER_T
{
int uiTimerID;
long lMilliSecond;
void(* lpProcessFunction)(void * pvData);
void * pvData;
} TIMER_T;

2.      定时器类

class Timer
{
public:
Timer();
int SetTimer(
long lMilliSecond, //the millisecond of timer
void (*_lpProcessFunction)(void * pvData),
void * pvData
);
bool CancleTimer(int ulTimerID);
bool GetInstanceStatus();
~Timer();
private:
static DWORD WINAPI ScanTimerQueue(LPVOID lp);
static int CmpFunc(TIMER_T * t1, TIMER_T * t2);
private:
static SortBinaryTree<TIMER_T> * m_pstSBT;
static int m_uiTimerID;
bool m_bInit;
HANDLE m_hScan;
std::map<int, TIMER_T *> m_map;
};

3.      定时器的设置

int Timer::SetTimer(
long lMilliSecond, //the millisecond of timer
void (*_lpProcessFunction)(void * pvData),
void * pvData
)
{
TIMER_T * stTimerInstc = (TIMER_T *)malloc(sizeof(TIMER_T));
if (!stTimerInstc)
{
return INVILID_TIMER_ID;
}
stTimerInstc->lpProcessFunction = _lpProcessFunction;
/*The GetTickCount() function will be zero when your system run more than 49.7 days.*/
stTimerInstc->lMilliSecond = GetTickCount() + lMilliSecond;
stTimerInstc->uiTimerID = ++m_uiTimerID;
stTimerInstc->pvData = pvData;
if (m_pstSBT->InsertTreeNode(stTimerInstc))
{
m_map.insert(std::pair<int,TIMER_T *>(m_uiTimerID, stTimerInstc));
return m_uiTimerID;
}
else
{
free(stTimerInstc);
stTimerInstc = NULL;
return INVILID_TIMER_ID;
}
}

4.      取消定时器

bool Timer::CancleTimer(int ulTimerID)
{
std::map<int, TIMER_T *>::iterator itor_map;
itor_map = m_map.find(ulTimerID);
if (itor_map == m_map.end())
{
return false;
}
if (m_pstSBT->DeleteTreeNode((void *)itor_map->second))
{
free(itor_map->second);
itor_map->second = NULL;
m_map.erase(itor_map);
return true;
}
else
{
return false;
}
}


5.      定时器扫描队列

DWORD WINAPI Timer::ScanTimerQueue(LPVOID lp)
{
LONG ulCurrTime;
while(1)
{
ulCurrTime = GetTickCount();
if (NULL != m_pstSBT->GetSmallestNode() &&
m_pstSBT->GetSmallestNode()->lMilliSecond <= ulCurrTime)
{
TIMER_T * pstTimer = m_pstSBT->DeleteSmallestNode();
if (NULL != pstTimer)
{
pstTimer->lpProcessFunction(pstTimer->pvData);
free(pstTimer);
pstTimer = NULL;
}
}
SLEEP(100);
}
return 0;
}


        总结:Timer实现了定时器的主要功能,设置定时器和取消定时器,同时,在设置定时器时通过提供一个回调函数来完成相关工作。定时器存储在SortBinaryTree中,便于扫描。

        存在的问题:由于在设置定时器的时候采用了GetTickCount()函数,因此限制了服务器的连续运行时间不得超过49.7天,在大型服务代码的编写中,这将通过其他替代函数完成这一类似功能。