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.为什么需要消息队列?当系统中出现“生产“和“消费“的速度或稳定性等因素不一致的时候,就需要消 ...
随机推荐
- Struts2开发步骤(及Struts2配置相关)
1.在web.xml定义Filter来拦截用户请求. <filter> <filter-name>struts2</fil ...
- js实现中文转拼音
首先需要注意ES6在严格模式下中常量太长会出问题,CHAR_DICT.FULL_DICT.POLYPHONE都是很大的常量,所以我都外部加载了,否则编译运行会有问题,先贴代码,常量在最后,如下: js ...
- 2016022605 - redis订阅发布
Redis的实现消息队列功能,消息发布者发送的消息,消息接收者接收发布者的消息.由该消息传送的链路被称为通道.在Redis客户端可以订阅任何数目的通道. 案例:给出一个客户端订阅一个通道名为redis ...
- windows相关小知识
获得本机MAC1 快捷键win+R打开运行窗口, 输入cmd回车进入控制台2 输入ipconfig -all 找到本地连接中的物理地址 根据IP获得MAC方法:1 进入cmd控制台,执行:ping ...
- sqlplus 打印很乱,而且很短就换行
set linesize 可以解决 设置行打印的字符长度,set linesize 400解决
- dispatch_semaphore
dispatch_semaphore 信号量基于计数器的一种多线程同步机制.在多个线程访问共有资源时候,会因为多线程的特性而引发数据出错的问题. dispatch_queue_t queue = di ...
- 【POJ1743】不可重叠最长重复子串
题意:求一个字符串里两个不重叠的最长重复子串 代码如下: #include<cstdio> #include<cstdlib> #include<cstring> ...
- QPixmap有缓冲区的
我想qt 中QPixmap这个类大家都很熟悉,它可以很简单的在标签上贴图:例如: QPixmap p; p.load("1.png"): label->setPixmap(p ...
- JSch - Java实现的SFTP(文件上传详解篇)(转)
JSch是Java Secure Channel的缩写.JSch是一个SSH2的纯Java实现.它允许你连接到一个SSH服务器,并且可以使用端口转发,X11转发,文件传输等,当然你也可以集成它的功能到 ...
- 【游戏框架】Phaser
PhaserDesktop and Mobile HTML5 game framework Phaser Examples