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.为什么需要消息队列?当系统中出现“生产“和“消费“的速度或稳定性等因素不一致的时候,就需要消 ...
随机推荐
- javascrip 分享到
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...
- node 后台ajax文件(同时支持http、https)
var http = require("http"), Url = require("url"), querystring = require('queryst ...
- ASP.NET MVC轻教程 Step By Step 10——模型验证
在使用表单获取用户输入的数据时,我们必须对数据进行有效性验证,因为来自网络的信息都是不可信的.同时也要给用户即时的反馈,避免让用户感到困惑.这就涉及到数据验证的范畴. 数据验证最直接的做法是在服务器端 ...
- Axure RP的版本控制
首先介绍一下Axure RP,Axure的发音是Ask-Sure,RP是Rapid Prototype的缩写,写到这里你知道了这是一款原型绘画工具.本节主要介绍Axure RP的版本管理也即Axure ...
- word的不同章节之间添加不同的页眉
1.点击空百处 2. 在页面布局中,找到分隔符,选择”连续“选项,即在空白处插入分隔符 特别注意:这里分隔符会出现换行现象,请选择空白处,不要影响原先布局 3. 当编辑下一个页眉时,点击“链接到前一条 ...
- tyvj P1209 - 拦截导弹 平面图最小割&&模型转化
P1209 - 拦截导弹 From admin Normal (OI)总时限:6s 内存限制:128MB 代码长度限制:64KB 背景 Background 实中编程者联盟为了培养技 ...
- prototype.js 源码解读(02)
如果你想研究一些比较大型的js框架的源码的话,本人建议你从其最初的版本开始研读,因为最初的版本东西少,易于研究,而后的版本基本都是在其基础上不断扩充罢了,所以,接下来我不准备完全解读prototype ...
- 你的 Docker 应用是安全的吗?
近一年来,Docker 已经逐渐成为 container 界的事实标准,成为技术人员不可或缺的技能之一,就像 Docker 宣称的那样,「Build,Ship,and Run Any App,Anyw ...
- struts2+jsp+jquery+Jcrop实现图片裁剪并上传
<1> 使用html标签上传需要裁剪的大图. <2> 在页面呈现大图,使用Jcrop(Jquery)对大图进行裁剪,并且可以进行预览. <3> 选择好截取部分之后发 ...
- BZOJ1610: [Usaco2008 Feb]Line连线游戏
1610: [Usaco2008 Feb]Line连线游戏 Time Limit: 5 Sec Memory Limit: 64 MBSubmit: 1301 Solved: 571[Submit ...