Thread.h
#pragma once
#include <Windows.h>
#include <iostream>
#include <assert.h>
#include <process.h>
using namespace std;
class CThread
{
public:
CThread();
virtual ~CThread();
HANDLE getHandle() const;
bool wait();
bool wait(DWORD timeoutMillsecs);
void start();
DWORD terminate(DWORD exitcode=0);
private:
virtual int run() = 0;
static unsigned int __stdcall threadFunction(void *threadParam);
void resetHandle();
private:
CThread(const CThread&);
CThread& operator = (const CThread&);
private:
HANDLE m_handle;
};
#include "StdAfx.h"
#include "Thread.h"
CThread::CThread():m_handle(NULL)
{
}
CThread::~CThread()
{
resetHandle();
}
HANDLE CThread::getHandle() const
{
return m_handle;
}
void CThread::start()
{
if (m_handle == NULL)
{
unsigned int _threadID = 0;
m_handle = (HANDLE)::_beginthreadex(0,
0,
threadFunction,
(void*)this,
0,
&_threadID
);
assert(m_handle!=NULL);
}
}
bool CThread::wait()
{
return wait(INFINITE);
}
bool CThread::wait(DWORD timeoutMillsecs)
{
bool _isOK = false;
if (NULL == m_handle)
{
return true;
}
DWORD _result = ::WaitForSingleObject(m_handle,timeoutMillsecs);
if (_result == WAIT_TIMEOUT)
{
_isOK = false;
}
if (_result == WAIT_OBJECT_0)
{
_isOK = true;
}
resetHandle();
return _isOK;
}
DWORD CThread::terminate(DWORD exitcode)
{
if (m_handle != NULL && ::TerminateThread(m_handle,exitcode))
{
m_handle = NULL;
return ERROR_SUCCESS;
}
else
{
return ::GetLastError();
}
return 0;
}
unsigned int __stdcall CThread::threadFunction(void *threadParam)
{
CThread *pThread = (CThread*)threadParam;
int _ret = pThread->run();
pThread->resetHandle();
return _ret;
}
void CThread::resetHandle()
{
if (m_handle)
{
::CloseHandle(m_handle);
m_handle =NULL;
}
}
EasyTimer.h
#pragma once
#include <Windows.h>
#include <iostream>
using namespace std;
class CTimeProcess
{
public:
CTimeProcess(){}
~CTimeProcess(){}
private:
void __init(){
LARGE_INTEGER nFreq;
QueryPerformanceFrequency(&nFreq);
m_millsecondsPerTick = 1000.0f / nFreq.QuadPart;
}
public:
__int64 gettime(){
static bool _bIsInit = false;
if (_bIsInit==false) {
__init();
_bIsInit = true;
}
LARGE_INTEGER nFreq;
QueryPerformanceCounter(&nFreq);
return ( __int64)(nFreq.QuadPart * m_millsecondsPerTick);
}
public:
static CTimeProcess* instance()
{
static CTimeProcess tp;
return &tp;
}
private:
double m_millsecondsPerTick;
};
#define CURTIME() CTimeProcess::instance()
//
class CEventHandle
{
public:
CEventHandle(){}
virtual ~CEventHandle(){}
virtual void processEvent() =0;
};
class CEventDemo:public CEventHandle
{
public:
CEventDemo(){
}
~CEventDemo(){}
void processEvent()
{
cout<<"hello, CEventDemo"<<endl<<endl;
}
};
class CEventSpecial:public CEventHandle
{
public:
CEventSpecial(){
}
~CEventSpecial(){}
void processEvent()
{
cout<<"hello, CEventSpecial"<<endl<<endl;
}
};
//
class CEasyTimer
{
public:
CEasyTimer();
~CEasyTimer(void);
public:
bool settimer( int uTimerID, __int64 uEclps, int triggertimes,CEventHandle& pevent);
bool killtimer( int uTimerID);
int getStatus( int uTimerID);
int getStatus(){return m_bStatus;}
void setStatus(int nStatus){ m_bStatus = nStatus;}
int getID() const { return m_uID ; }
void processTimer();
CEasyTimer* create( int uTimerID, __int64 uEclps, int triggertimes);
__int64 getlocaltime();
private:
int m_bStatus;
int m_uID;
__int64 m_uEclps;
__int64 m_begaintime;
int m_triggertimes;
int m_nTriggled;
CEventHandle* m_pehandle;
};
enum eTimerStatus
{
ETS_NONE,
ETS_RUN,
ETS_CLOSED,
ETS_COUNT
};
EasyTimer.cpp
#include "StdAfx.h"
#include "EasyTimer.h"
#include "TimerManager.h"
CEasyTimer::CEasyTimer():m_nTriggled(0)
{
TIMERMANAGER()->start();
}
CEasyTimer::~CEasyTimer(void)
{
}
bool CEasyTimer::settimer( int uTimerID, __int64 uEclps, int triggertimes,CEventHandle& pevent)
{
setStatus(ETS_RUN);
m_pehandle = &pevent;
bool _bSetResult = TIMERMANAGER()->add((this->create(uTimerID,uEclps,triggertimes)));
if (_bSetResult)
{
m_begaintime = getlocaltime();
return true;
}
return false;
}
CEasyTimer* CEasyTimer::create( int uTimerID, __int64 uEclps, int triggertimes)
{
m_uID = uTimerID;
m_uEclps = uEclps;
m_triggertimes = triggertimes;
return this;
}
bool CEasyTimer::killtimer( int uTimerID)
{
return TIMERMANAGER()->del(uTimerID);
}
int CEasyTimer::getStatus( int uTimerID)
{
return TIMERMANAGER()->getStatus(uTimerID);
}
__int64 CEasyTimer::getlocaltime()
{
return CURTIME()->gettime();
}
void CEasyTimer::processTimer()
{
__int64 _now=getlocaltime();
if ( (getStatus() == ETS_RUN) && (m_nTriggled < m_triggertimes) )
{
if (_now - m_begaintime >= m_uEclps*1000)
{
m_nTriggled++;//触发了一次
//处理之
m_begaintime = getlocaltime();
m_pehandle->processEvent();
}
}
else //触发的次数用完了
{
setStatus(ETS_CLOSED);
//killtimer(m_uID);
}
}
TimerManager.h
#pragma once
#include "Thread.h"
#include "EasyTimer.h"
#include <map>
using namespace std;
class CTimerManager :public CThread
{
CTimerManager(void);
~CTimerManager(void);
public:
static CTimerManager* instance();
bool add(CEasyTimer* newTimer);
inline int getCount() const { return m_nTotalTimerCount ;}
bool del( int uTimerID);
int getStatus( int uTimerID);
public:
int run();
private:
int m_nTotalTimerCount;
typedef map<int,CEasyTimer*> m_mapTimerType;
m_mapTimerType m_mapTimer;
};
#define TIMERMANAGER() CTimerManager::instance()
TimerManager.cpp
#include "StdAfx.h"
#include "TimerManager.h"
CTimerManager::CTimerManager(void)
{
}
CTimerManager::~CTimerManager(void)
{
}
CTimerManager* CTimerManager::instance()
{
static CTimerManager _instance;
return &_instance;
}
bool CTimerManager::add(CEasyTimer* newTimer)
{
map<int,CEasyTimer*>::iterator _iter=m_mapTimer.find(newTimer->getID());
if ( _iter != m_mapTimer.end())
{
return false;
}
m_mapTimer.insert(make_pair<int,CEasyTimer*>(newTimer->getID(),newTimer));
m_nTotalTimerCount++;
return true;
}
bool CTimerManager::del( int uTimerID)
{
map<int,CEasyTimer*>::iterator _iter=m_mapTimer.find(uTimerID);
if ( _iter != m_mapTimer.end() )
{
m_mapTimer.erase(_iter);
m_nTotalTimerCount--;
return true;
}
return false;
}
int CTimerManager::run()
{
while (true)
{
map< int,CEasyTimer*>::iterator _itBegain = m_mapTimer.begin();
map< int,CEasyTimer*>::iterator _itEnd = m_mapTimer.end();
map< int,CEasyTimer*>::iterator _it=_itBegain;
while ( getCount() && (_it != _itEnd ))
{
_it->second->processTimer();
_it++;
}
//for check timer status and ease them if the status we get is the time should be kill
if(getCount())
{
map< int,CEasyTimer*>::iterator __it=_itBegain;
while (__it != _itEnd)
{
if (__it->second->getStatus() ==ETS_CLOSED)
{
map< int,CEasyTimer*>::iterator __temp;
__temp = __it;
++__it;
int _id = __temp->second->getID();
__temp->second->killtimer(_id);
continue;
}
++__it;
}
}
}
return 0;
}
int CTimerManager::getStatus( int uTimerID)
{
map<int,CEasyTimer*>::iterator _iter=m_mapTimer.find(uTimerID);
if ( _iter != m_mapTimer.end() )
{
return _iter->second->getStatus(uTimerID);
}
return ETS_NONE;
}
main.cpp
#include "stdafx.h"
#include "EasyTimer.h"
#define MEM_RELEASE(point) \
{ \
if(point){ \
delete point; \
point = 0 ;\
} \
}
int main()
{
CEventHandle *pEvent = new CEventDemo();
CEasyTimer *pEasyTime=new CEasyTimer();
pEasyTime->settimer(100,1,10,*pEvent);//ID:100 每隔一秒触发一次,总共触发10次
CEventHandle *pEvent2 = new CEventSpecial();
CEasyTimer *pEasyTime2=new CEasyTimer();
pEasyTime2->settimer(101,2,10,*pEvent2);
while (true);
MEM_RELEASE(pEvent);
MEM_RELEASE(pEasyTime);
MEM_RELEASE(pEvent2);
MEM_RELEASE(pEasyTime2);
return 0;
};
注:这个代码例子有个bug,就是定时器数量级上升时,定时器的线程循环非常耗费,要进行许多无效的遍历,所以造成时间延迟。
可以通过修改定时器的map结构来解决:
1,修改定时器的map为:map<currtime,timestruct>, currtime就是pc当前时间,timestruct是当前遍历的定时器结构,
2,因为map内部使用红黑树生成的,能自动排序key(默认从小到大),所以if判断当前时间是否小于当前遍历到的定时器时间是否满足触发,如果不满足,break。否则将当前需要触发的定时器insert进一个全局队列中,当上一轮循环结束后遍历队列循环进行定时器触发处理。