c++ timer基于win消息队列
能够承载10w个timer通信执行,说关闭就关闭,里面用了一个比較巧妙的线程处理,呵呵10W个timer就10多个线程,请大牛不要笑话,供新手学习之用
#pragma once
#include <Windows.h>
typedef void (CALLBACK* UXTIMERCALLBACK)(DWORD,void*);
#include <map>
#define G_UXTimerQueue (CUXTimer::GetInstance())
//--------------------------------------------------------------------------------------
typedef struct tegTIMERINFO
{
HANDLE hEvent;
DWORD dwEventID;
UXTIMERCALLBACK callback;
void* pEvent;
void* pThis;
HANDLE hCmpEvent;
}TIMERINFO ;
typedef std::map<DWORD,TIMERINFO*> TIMERQUEUE;
//-------------------------------------------------------------------------------------
class CUXTimer
{
public:
CUXTimer();
virtual ~CUXTimer();
void SetTimer(DWORD dwIdEvent,DWORD dwTime,UXTIMERCALLBACK callBack,void* p);
void KillTimer(DWORD dwIdEvent);
static CUXTimer& GetInstance()
{
static CUXTimer u;
return u;
}
inline TIMERQUEUE& GetTimerQueue()
{
return m_timer_queue;
};
inline HANDLE GetTimerQueueHandle()
{
return m_hTimerQueue;
};
inline DWORD GetIdEvent()
{
InterlockedIncrement((LONG*)&m_longIdEvent);
if(m_longIdEvent==UINT_MAX)
m_longIdEvent = 1;
return (DWORD)m_longIdEvent;
}
protected:
private:
HANDLE m_hTimerQueue;
TIMERQUEUE m_timer_queue;
HANDLE m_hGuardThd;
private:
unsigned long m_longIdEvent;
static void WINAPI TimerFunc(void*,bool);
static unsigned int __stdcall GuardThd(PVOID p);
public:
CRITICAL_SECTION m_cs_timer_queue;
static CUXTimer* m_pThis;
};
//--------------------------------------------------------------------------------------
//cpp
#include "stdafx.h"
#include "UXTimerQueue.h"
#include <process.h>
CUXTimer* CUXTimer::m_pThis = NULL;
//--------------------------------------------------------------------------------------------------------
CUXTimer::CUXTimer():m_longIdEvent(0)
{
m_hTimerQueue = CreateTimerQueue();
InitializeCriticalSection(&m_cs_timer_queue);
m_pThis = this;
m_hGuardThd = (HANDLE)_beginthreadex(NULL,0,GuardThd,0,0,0);
}
//--------------------------------------------------------------------------------------------------------
CUXTimer:: ~CUXTimer()
{
DeleteTimerQueue(m_hTimerQueue);
DeleteCriticalSection(&m_cs_timer_queue);
m_timer_queue.clear();
}
//--------------------------------------------------------------------------------------------------------
void CUXTimer::SetTimer(DWORD dwIdEvent,DWORD dwTime,UXTIMERCALLBACK callBack,void* p)
{
TIMERQUEUE::iterator it;
EnterCriticalSection(&m_cs_timer_queue);
TIMERINFO* t=new TIMERINFO;
t->dwEventID = dwIdEvent;
t->callback = callBack;
t->pEvent = p;
t->pThis = this;
t->hCmpEvent = CreateEvent(NULL,1,1,0);
ResetEvent(t->hCmpEvent);
if(!CreateTimerQueueTimer(&t->hEvent,m_hTimerQueue,(WAITORTIMERCALLBACK)TimerFunc,(void*)t->dwEventID,dwTime,dwTime,WT_EXECUTEINIOTHREAD))
{
if (!t->hEvent)
{
DeleteTimerQueueTimer(m_hTimerQueue,t->hEvent,t->hCmpEvent);
if (t)
{
delete t;
t = NULL;
}
LeaveCriticalSection(&m_cs_timer_queue);
return;
}
}
//预防在维护线程没有清空原有的timer,这时候这个timer反复利用,须要释放先前一个timer
if ( (it = m_timer_queue.find(dwIdEvent) ) != m_timer_queue.end())
{
if (it->second)
{
delete it->second;
it->second = NULL;
}
m_timer_queue.erase(it);
}
//将timer加入到map中用于保存
m_timer_queue.insert(std::make_pair(dwIdEvent,t));
LeaveCriticalSection(&m_cs_timer_queue);
}
//--------------------------------------------------------------------------------------------------------
void CUXTimer::KillTimer(DWORD dwIdEvent)
{
EnterCriticalSection(&m_cs_timer_queue);
TIMERQUEUE::iterator it = m_timer_queue.find(dwIdEvent);
if (it!=m_timer_queue.end())
{
it->second->pThis = NULL;
if (it->second->hEvent)
{
DeleteTimerQueueTimer(m_hTimerQueue,it->second->hEvent,it->second->hCmpEvent);
OutputDebugStringA("KILLTIMER/n");
}
}
LeaveCriticalSection(&m_cs_timer_queue);
}
//--------------------------------------------------------------------------------------------------------
void CUXTimer::TimerFunc(void* p,bool b)
{
EnterCriticalSection(&G_UXTimerQueue.m_cs_timer_queue);
DWORD dwEventID = (DWORD)p;
TIMERQUEUE::iterator it1 = m_pThis->m_timer_queue.find(dwEventID);
if (it1 != m_pThis->m_timer_queue.end())
{
if (it1->second->pThis)
{
it1->second->callback(dwEventID,it1->second->pEvent);
}
}
LeaveCriticalSection(&G_UXTimerQueue.m_cs_timer_queue);
}
//--------------------------------------------------------------------------------------------------------
unsigned int __stdcall CUXTimer::GuardThd(PVOID p)
{
while(1)
{
if (m_pThis->m_timer_queue.size()>0)
{
EnterCriticalSection(&G_UXTimerQueue.m_cs_timer_queue);
for (TIMERQUEUE::iterator it = m_pThis->m_timer_queue.begin();it != m_pThis->m_timer_queue.end();)
{
if(WaitForSingleObject(it->second->hCmpEvent,0) == WAIT_OBJECT_0)
{
CloseHandle(it->second->hCmpEvent);
it->second->hCmpEvent = NULL;
if (it->second)
{
delete it->second;
it->second = NULL;
}
m_pThis->m_timer_queue.erase(it++);
OutputDebugStringA("REAL_KILLTIMER/n");
}
else
it++;
}
LeaveCriticalSection(&G_UXTimerQueue.m_cs_timer_queue);
}
Sleep(500);
}
return 0;
}
//--------------------------------------------------------------------------------------------------------
//用法
int i = 0;
for (i = 0;i<10000;i++)
{
G_UXTimerQueue.SetTimer(i,500,timer,(void*)i); //启动
}
Sleep(10000);
i = 0;
for (;i<10000;i++)
{
G_UXTimerQueue.KillTimer(i); //停止
}
Sleep(10000);
for (i = 0;i<10000;i++)
{
G_UXTimerQueue.SetTimer(i,500,timer,(void*)i);
}
Sleep(10000);
i = 0;
for (;i<10000;i++)
{
G_UXTimerQueue.KillTimer(i);
}
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。