377 lines
7.7 KiB
C++
377 lines
7.7 KiB
C++
|
|
#include "StdAfx.h"
|
|||
|
|
#include "TimerEngine.h"
|
|||
|
|
#include "TraceService.h"
|
|||
|
|
|
|||
|
|
//ö<><C3B6>
|
|||
|
|
enum
|
|||
|
|
{
|
|||
|
|
TIMER_SPACE = 25, //ʱ<><CAB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
TIMER_LEAD = TIMER_SPACE*20 //<2F><>ǰʱ<C7B0><CAB1>
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
|
|||
|
|
//////////////////////////////////////////////////////////////////////////
|
|||
|
|
|
|||
|
|
//<2F><><EFBFBD>캯<EFBFBD><ECBAAF>
|
|||
|
|
CTimerThread::CTimerThread(void)
|
|||
|
|
{
|
|||
|
|
m_pTimerEngine = NULL;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
CTimerThread::~CTimerThread(void)
|
|||
|
|
{
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
//<2F><><EFBFBD>ú<EFBFBD><C3BA><EFBFBD>
|
|||
|
|
bool CTimerThread::InitThread(CTimerEngine * pTimerEngine)
|
|||
|
|
{
|
|||
|
|
if (pTimerEngine == NULL) return false;
|
|||
|
|
|
|||
|
|
//<2F><><EFBFBD>ñ<EFBFBD><C3B1><EFBFBD>
|
|||
|
|
m_pTimerEngine = pTimerEngine;
|
|||
|
|
|
|||
|
|
return true;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
//<2F><><EFBFBD>к<EFBFBD><D0BA><EFBFBD>
|
|||
|
|
bool CTimerThread::OnEventThreadRun()
|
|||
|
|
{
|
|||
|
|
ASSERT(m_pTimerEngine != NULL);
|
|||
|
|
Sleep(TIMER_SPACE);
|
|||
|
|
m_pTimerEngine->OnTimerThreadSink();
|
|||
|
|
return true;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
//////////////////////////////////////////////////////////////////////////
|
|||
|
|
|
|||
|
|
//<2F><><EFBFBD>캯<EFBFBD><ECBAAF>
|
|||
|
|
CTimerEngine::CTimerEngine(void)
|
|||
|
|
{
|
|||
|
|
m_bService = false;
|
|||
|
|
//m_pIQueueServiceSink = NULL;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
CTimerEngine::~CTimerEngine(void)
|
|||
|
|
{
|
|||
|
|
//ֹͣ<CDA3><D6B9><EFBFBD><EFBFBD>
|
|||
|
|
ConcludeService();
|
|||
|
|
|
|||
|
|
//<2F><><EFBFBD><EFBFBD><EFBFBD>ڴ<EFBFBD>
|
|||
|
|
tagTimerItem * pTimerItem = NULL;
|
|||
|
|
for (INT_PTR i = m_TimerItemFree.GetCount()-1; i>=0; i--)
|
|||
|
|
{
|
|||
|
|
pTimerItem = m_TimerItemFree[i];
|
|||
|
|
ASSERT(pTimerItem != NULL);
|
|||
|
|
SafeDelete(pTimerItem);
|
|||
|
|
}
|
|||
|
|
for (INT_PTR i = m_TimerItemActive.GetCount()-1; i>=0; i--)
|
|||
|
|
{
|
|||
|
|
pTimerItem = m_TimerItemActive[i];
|
|||
|
|
ASSERT(pTimerItem != NULL);
|
|||
|
|
SafeDelete(pTimerItem);
|
|||
|
|
}
|
|||
|
|
m_TimerItemFree.RemoveAll();
|
|||
|
|
m_TimerItemActive.RemoveAll();
|
|||
|
|
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
//<2F>ӿڲ<D3BF>ѯ
|
|||
|
|
void * CTimerEngine::QueryInterface(const IID & Guid, DWORD dwQueryVer)
|
|||
|
|
{
|
|||
|
|
QUERYINTERFACE(ITimerEngine, Guid, dwQueryVer);
|
|||
|
|
QUERYINTERFACE_IUNKNOWNEX(ITimerEngine, Guid, dwQueryVer);
|
|||
|
|
return NULL;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
//<2F><><EFBFBD>ö<EFBFBD>ʱ<EFBFBD><CAB1>
|
|||
|
|
bool CTimerEngine::SetTimer(DWORD dwTimerID, DWORD dwElapse, DWORD dwRepeat, WPARAM dwBindParameter)
|
|||
|
|
{
|
|||
|
|
//Ч<><D0A7><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
ASSERT(dwRepeat > 0L);
|
|||
|
|
if (dwRepeat == 0) return false;
|
|||
|
|
|
|||
|
|
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Դ
|
|||
|
|
CWHDataLocker lock(m_CriticalSection);
|
|||
|
|
|
|||
|
|
//<2F><><EFBFBD>Ҷ<EFBFBD>ʱ<EFBFBD><CAB1>
|
|||
|
|
bool bTimerExist = false;
|
|||
|
|
tagTimerItem * pTimerItem = NULL;
|
|||
|
|
for (INT_PTR i = m_TimerItemActive.GetCount()-1; i>=0; i-- )
|
|||
|
|
{
|
|||
|
|
pTimerItem = m_TimerItemActive[i];
|
|||
|
|
ASSERT(pTimerItem != NULL);
|
|||
|
|
if (pTimerItem->wTimerID == dwTimerID)
|
|||
|
|
{
|
|||
|
|
bTimerExist = true;
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1>
|
|||
|
|
if ( !bTimerExist )
|
|||
|
|
{
|
|||
|
|
INT_PTR nFreeCount = m_TimerItemFree.GetCount();
|
|||
|
|
if (nFreeCount > 0)
|
|||
|
|
{
|
|||
|
|
pTimerItem = m_TimerItemFree[nFreeCount-1];
|
|||
|
|
ASSERT(pTimerItem != NULL);
|
|||
|
|
m_TimerItemFree.RemoveAt(nFreeCount - 1);
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
try
|
|||
|
|
{
|
|||
|
|
pTimerItem = new tagTimerItem;
|
|||
|
|
ASSERT(pTimerItem != NULL);
|
|||
|
|
if (pTimerItem == NULL) return false;
|
|||
|
|
}
|
|||
|
|
catch (...)
|
|||
|
|
{
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
//<2F><><EFBFBD>ò<EFBFBD><C3B2><EFBFBD>
|
|||
|
|
ASSERT(pTimerItem != NULL);
|
|||
|
|
pTimerItem->wTimerID = dwTimerID;
|
|||
|
|
pTimerItem->wBindParam = dwBindParameter;
|
|||
|
|
pTimerItem->dwElapse = dwElapse-(dwElapse%TIMER_SPACE);
|
|||
|
|
pTimerItem->dwRepeatTimes = dwRepeat;
|
|||
|
|
pTimerItem->dwDestTime = GetTickCount();
|
|||
|
|
//<2F><>ǰ20<32><30><EFBFBD><EFBFBD><EFBFBD>Ƚ<EFBFBD><C8BD><EFBFBD>֪ͨ - TIMER_SPACE * 20
|
|||
|
|
if ( 1 == pTimerItem->dwRepeatTimes )
|
|||
|
|
{
|
|||
|
|
if (pTimerItem->dwElapse>TIMER_SPACE+TIMER_LEAD)
|
|||
|
|
{
|
|||
|
|
pTimerItem->dwDestTime += pTimerItem->dwElapse-TIMER_LEAD;
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
pTimerItem->dwDestTime += TIMER_SPACE;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
pTimerItem->dwDestTime += pTimerItem->dwElapse;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
//<2F><><EFBFBD>ʱ<EEB6A8><CAB1>
|
|||
|
|
if ( !bTimerExist )
|
|||
|
|
{
|
|||
|
|
m_TimerItemActive.Add(pTimerItem);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return true;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
//ɾ<><C9BE><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1>
|
|||
|
|
bool CTimerEngine::KillTimer(DWORD dwTimerID)
|
|||
|
|
{
|
|||
|
|
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Դ
|
|||
|
|
CWHDataLocker lock(m_CriticalSection);//
|
|||
|
|
|
|||
|
|
//<2F><><EFBFBD>Ҷ<EFBFBD>ʱ<EFBFBD><CAB1>
|
|||
|
|
tagTimerItem * pTimerItem = NULL;
|
|||
|
|
for ( INT_PTR i = m_TimerItemActive.GetCount()-1; i>=0; i-- )
|
|||
|
|
{
|
|||
|
|
pTimerItem = m_TimerItemActive[i];
|
|||
|
|
ASSERT(pTimerItem != NULL);
|
|||
|
|
if (pTimerItem->wTimerID == dwTimerID)
|
|||
|
|
{
|
|||
|
|
m_TimerItemActive.RemoveAt(i);
|
|||
|
|
m_TimerItemFree.Add(pTimerItem);
|
|||
|
|
return true;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
//ɾ<><C9BE><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1>
|
|||
|
|
bool CTimerEngine::KillAllTimer()
|
|||
|
|
{
|
|||
|
|
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Դ
|
|||
|
|
CWHDataLocker lock(m_CriticalSection);//
|
|||
|
|
|
|||
|
|
//ɾ<><C9BE><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1>
|
|||
|
|
m_TimerItemFree.Append(m_TimerItemActive);
|
|||
|
|
m_TimerItemActive.RemoveAll();
|
|||
|
|
|
|||
|
|
return true;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
//<2F><>ʼ<EFBFBD><CABC><EFBFBD><EFBFBD>
|
|||
|
|
bool CTimerEngine::StartService()
|
|||
|
|
{
|
|||
|
|
//Ч<><D0A7>״̬
|
|||
|
|
if (m_bService)
|
|||
|
|
{
|
|||
|
|
CTraceService::TraceString(TEXT("<EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ظ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>"), TraceLevel_Warning);
|
|||
|
|
return true;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
//<2F><><EFBFBD>ñ<EFBFBD><C3B1><EFBFBD>
|
|||
|
|
if ( !m_TimerThread.InitThread(this) )
|
|||
|
|
{
|
|||
|
|
CTraceService::TraceString(TEXT("<EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>̷߳<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʼ<EFBFBD><EFBFBD>ʧ<EFBFBD><EFBFBD>"), TraceLevel_Exception);
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
if ( !m_TimerThread.StartThread() )
|
|||
|
|
{
|
|||
|
|
CTraceService::TraceString(TEXT("<EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>̷߳<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʧ<EFBFBD><EFBFBD>"), TraceLevel_Exception);
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
SetThreadPriority(m_TimerThread.GetThreadHandle(), REALTIME_PRIORITY_CLASS);
|
|||
|
|
|
|||
|
|
//<2F><><EFBFBD>ñ<EFBFBD><C3B1><EFBFBD>
|
|||
|
|
m_bService = true;
|
|||
|
|
|
|||
|
|
return true;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
//ֹͣ<CDA3><D6B9><EFBFBD><EFBFBD>
|
|||
|
|
bool CTimerEngine::ConcludeService()
|
|||
|
|
{
|
|||
|
|
//<2F><><EFBFBD>ñ<EFBFBD><C3B1><EFBFBD>
|
|||
|
|
m_bService = false;
|
|||
|
|
|
|||
|
|
//ֹͣ<CDA3>߳<EFBFBD>
|
|||
|
|
m_TimerThread.ConcludeThread(INFINITE);
|
|||
|
|
|
|||
|
|
//<2F><><EFBFBD>ñ<EFBFBD><C3B1><EFBFBD>
|
|||
|
|
m_TimerItemFree.Append(m_TimerItemActive);
|
|||
|
|
m_TimerItemActive.RemoveAll();
|
|||
|
|
|
|||
|
|
m_QueueServiceEvent.SetQueueServiceSink(NULL);
|
|||
|
|
|
|||
|
|
return true;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
//<2F><><EFBFBD>ýӿ<C3BD>
|
|||
|
|
bool CTimerEngine::SetTimerEngineEvent(IUnknownEx * pIUnknownEx)
|
|||
|
|
{
|
|||
|
|
//Ч<><D0A7><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
ASSERT(pIUnknownEx != NULL);
|
|||
|
|
ASSERT( !m_bService );
|
|||
|
|
if (m_bService) return false;
|
|||
|
|
if (pIUnknownEx == NULL) return false;
|
|||
|
|
|
|||
|
|
////<2F><><EFBFBD>ýӿ<C3BD>
|
|||
|
|
//ASSERT(pIUnknownEx != NULL);
|
|||
|
|
//m_pIQueueServiceSink = QUERY_OBJECT_PTR_INTERFACE(pIUnknownEx, IQueueServiceSink);
|
|||
|
|
//ASSERT(m_pIQueueServiceSink != NULL);
|
|||
|
|
//return (m_pIQueueServiceSink != NULL);
|
|||
|
|
|
|||
|
|
//<2F><><EFBFBD>ýӿ<C3BD>
|
|||
|
|
if ( !m_QueueServiceEvent.SetQueueServiceSink(pIUnknownEx) )
|
|||
|
|
{
|
|||
|
|
CTraceService::TraceString(TEXT("<EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>봥<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʧ<EFBFBD><EFBFBD>"), TraceLevel_Exception);
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return true;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
//<2F><>ʱ<EFBFBD><CAB1>֪ͨ
|
|||
|
|
void CTimerEngine::OnTimerThreadSink()
|
|||
|
|
{
|
|||
|
|
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
CWHDataLocker lock(m_CriticalSection);//
|
|||
|
|
|
|||
|
|
//<2F><>ѯ<EFBFBD><D1AF>ʱ<EFBFBD><CAB1>
|
|||
|
|
tagTimerItem * pTimerItem = NULL;
|
|||
|
|
DWORD dwTickCount=GetTickCount();
|
|||
|
|
bool bKillTimer=false;
|
|||
|
|
for (INT_PTR i = m_TimerItemActive.GetCount() - 1; i >= 0; i--)
|
|||
|
|
{
|
|||
|
|
//Ч<><D0A7><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
pTimerItem = m_TimerItemActive[i];
|
|||
|
|
ASSERT(pTimerItem != NULL);
|
|||
|
|
if (pTimerItem == NULL) return;
|
|||
|
|
ASSERT(pTimerItem->dwDestTime != 0);
|
|||
|
|
|
|||
|
|
//<2F><>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
bKillTimer = false;
|
|||
|
|
if (dwTickCount>=pTimerItem->dwDestTime)
|
|||
|
|
{
|
|||
|
|
//try
|
|||
|
|
//{
|
|||
|
|
// BYTE cbBuffer[MAX_ASYNCHRONISM_DATA] = {0}; //<2F><><EFBFBD>ջ<EFBFBD><D5BB><EFBFBD>
|
|||
|
|
// //Ͷ<><CDB6><EFBFBD><EFBFBD>Ϣ
|
|||
|
|
// NTY_TimerEvent * pTimerEvent = (NTY_TimerEvent *)cbBuffer;
|
|||
|
|
// pTimerEvent->dwTimerID = pTimerItem->wTimerID;
|
|||
|
|
// pTimerEvent->dwBindParameter = pTimerItem->wBindParam;
|
|||
|
|
|
|||
|
|
// m_pIQueueServiceSink->OnQueueServiceSink(EVENT_TIMER, cbBuffer, sizeof(NTY_TimerEvent));
|
|||
|
|
//}
|
|||
|
|
//catch (...) { }
|
|||
|
|
|
|||
|
|
m_QueueServiceEvent.PostTimerEvent(pTimerItem->wTimerID, pTimerItem->wBindParam);
|
|||
|
|
|
|||
|
|
//<2F><><EFBFBD>ô<EFBFBD><C3B4><EFBFBD>
|
|||
|
|
if (pTimerItem->dwRepeatTimes != TIMES_INFINITY)
|
|||
|
|
{
|
|||
|
|
ASSERT(pTimerItem->dwRepeatTimes > 0);
|
|||
|
|
pTimerItem->dwRepeatTimes--;
|
|||
|
|
if (pTimerItem->dwRepeatTimes == 0L)
|
|||
|
|
{
|
|||
|
|
bKillTimer = true;
|
|||
|
|
m_TimerItemActive.RemoveAt(i);
|
|||
|
|
m_TimerItemFree.Add(pTimerItem);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
//<2F><><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1>
|
|||
|
|
if ( !bKillTimer )//<2F><>ǰ20<32><30><EFBFBD><EFBFBD><EFBFBD>Ƚ<EFBFBD><C8BD><EFBFBD>֪ͨ - TIMER_SPACE * 20
|
|||
|
|
{
|
|||
|
|
if ( 1 == pTimerItem->dwRepeatTimes )
|
|||
|
|
{
|
|||
|
|
if (pTimerItem->dwElapse>TIMER_SPACE+TIMER_LEAD)
|
|||
|
|
{
|
|||
|
|
pTimerItem->dwDestTime += pTimerItem->dwElapse-TIMER_LEAD;
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
pTimerItem->dwDestTime += TIMER_SPACE;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
pTimerItem->dwDestTime += pTimerItem->dwElapse;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
//////////////////////////////////////////////////////////////////////////
|
|||
|
|
|
|||
|
|
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
extern "C" __declspec(dllexport) void * CreateTimerEngine(const GUID & Guid, DWORD dwInterfaceVer)
|
|||
|
|
{
|
|||
|
|
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
CTimerEngine * pTimerEngine = NULL;
|
|||
|
|
try
|
|||
|
|
{
|
|||
|
|
pTimerEngine = new CTimerEngine();
|
|||
|
|
if (pTimerEngine == NULL) throw TEXT("<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʧ<EFBFBD><EFBFBD>");
|
|||
|
|
void * pObject = pTimerEngine->QueryInterface(Guid, dwInterfaceVer);
|
|||
|
|
if (pObject == NULL) throw TEXT("<EFBFBD>ӿڲ<EFBFBD>ѯʧ<EFBFBD><EFBFBD>");
|
|||
|
|
return pObject;
|
|||
|
|
}
|
|||
|
|
catch (...) {}
|
|||
|
|
|
|||
|
|
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
SafeDelete(pTimerEngine);
|
|||
|
|
return NULL;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
//////////////////////////////////////////////////////////////////////////
|