Files
wnmj/Servers/服务器组件/内核引擎/TimerEngine.cpp

377 lines
7.7 KiB
C++
Raw Normal View History

2026-02-13 14:34:15 +08:00
#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;
}
//////////////////////////////////////////////////////////////////////////