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);
}
c++ timer基于win消息队列的更多相关文章
- 基于工作组消息队列高可用&msmq-wcf故障
场景: msmq 1# server故障手工切换到2# server,msmq-wcf service宿主服务重启后,无法成功读取消息,状似service不工作.无法监听到数据传输. 解决过程: 反复 ...
- 消息队列(Message Queue)简介及其使用
消息队列(Message Queue)简介及其使用 摘要:利用 MSMQ(Microsoft Message Queue),应用程序开发人员可以通过发送和接收消息方便地与应用程序进行快速可靠的通信.消 ...
- WCF分布式开发步步为赢(13):WCF服务离线操作与消息队列MSMQ
之前曾经写过一个关于MSMQ消息队列的文章:WCF分布式开发必备知识(1):MSMQ消息队列 ,当时的目的也是用它来作为学习WCF 消息队列MSMQ编程的基础文章.在那篇文章里,我们详细介绍了MSMQ ...
- 基于redis的延迟消息队列设计
需求背景 用户下订单成功之后隔20分钟给用户发送上门服务通知短信 订单完成一个小时之后通知用户对上门服务进行评价 业务执行失败之后隔10分钟重试一次 类似的场景比较多 简单的处理方式就是使用定时任务 ...
- 基于redis的延迟消息队列设计(转)
需求背景 用户下订单成功之后隔20分钟给用户发送上门服务通知短信 订单完成一个小时之后通知用户对上门服务进行评价 业务执行失败之后隔10分钟重试一次 类似的场景比较多 简单的处理方式就是使用定时任务 ...
- Delayer 基于 Redis 的延迟消息队列中间件
Delayer 基于 Redis 的延迟消息队列中间件,采用 Golang 开发,支持 PHP.Golang 等多种语言客户端. 参考 有赞延迟队列设计 中的部分设计,优化后实现. 项目链接:http ...
- 项目分布式部署那些事(1):ONS消息队列、基于Redis的Session共享,开源共享
因业务发展需要现在的系统不足以支撑现在的用户量,于是我们在一周之前着手项目的性能优化与分布式部署的相关动作. 概况 现在的系统是基于RabbitHub(一套开源的开发时框架)和Rabbit.WeiXi ...
- HQueue:基于HBase的消息队列
HQueue:基于HBase的消息队列 凌柏 1. HQueue简介 HQueue是一淘搜索网页抓取离线系统团队基于HBase开发的一套分布式.持久化消息队列.它利用HTable存储消息数据 ...
- [转载] 基于Redis实现分布式消息队列
转载自http://www.linuxidc.com/Linux/2015-05/117661.htm 1.为什么需要消息队列?当系统中出现“生产“和“消费“的速度或稳定性等因素不一致的时候,就需要消 ...
随机推荐
- 百度地图API绘制带头箭头的折线
源代码: <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" co ...
- float浮动引起的ul高度崩溃与overflow的关系
今天遇到的问题真的让人不得不吐槽,因为一个很小的问题,花费了半天的时间来才解决这个问题.一直认为自己对Html与Css了解应该算蛮不错的,但是今天遇到的事情让我不得不反省自己的学习心态上的错误 ...
- 关于linux开机自启
/etc/rc.d/rc.local 是在系统最后启动,必须和其他rc.0 - rcN文件具有755权限
- 浅谈Exchange 2013开发-如何操作邮件的附件
因为项目中客户有一个的要求,所以这个Exchange前段时间搞的我很是头疼,没接触过这个东西,但是现在看来,纸老虎一个.希望我的经验可以帮助初次接触它的人少走一些弯路! 简单介绍一下:客户要求在自己的 ...
- ASP.NET MVC轻教程 Step By Step 10——模型验证
在使用表单获取用户输入的数据时,我们必须对数据进行有效性验证,因为来自网络的信息都是不可信的.同时也要给用户即时的反馈,避免让用户感到困惑.这就涉及到数据验证的范畴. 数据验证最直接的做法是在服务器端 ...
- 关于UPdate用法的
updaterestore_base set restore_base.localcost =(select localcost from [nt2000\cpi].chongia2. ...
- classpath目录
WEB-INF/ 是资源目录, 客户端不能直接访问, 这话是没错,不过现在的IDE编译器在编译时会把src下的文件(是文件,不是.java)移到WEB-INF/classes下.不过值得注意的是,sp ...
- Seven Steps to Success Machine Learning in Practice
Seven Steps to Success Machine Learning in Practice Project failures in IT are all too common. The r ...
- In machine learning, is more data always better than better algorithms?
In machine learning, is more data always better than better algorithms? No. There are times when mor ...
- hibernate异常:Could not determine type for: java.util.Set
根本原因:我实体类中的类型是raw,没法直接实例化的类型.private List<String> rightChoices;private Set<String> multi ...