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.为什么需要消息队列?当系统中出现“生产“和“消费“的速度或稳定性等因素不一致的时候,就需要消 ...
随机推荐
- 请大神帮忙解决 jquery 控制 li 标签问题
<li class="active"><a href="#1" data-toggle="tab">日志详细情况&l ...
- MyISAM 和 InnoDB 讲解[转]
MyISAM 和 InnoDB 讲解 InnoDB和MyISAM是许多人在使用MySQL时最常用的两个表类型,这两个表类型各有优劣,视具体应用而定.基本的差别为:MyISAM类型不支持事务处理等高级处 ...
- MVC5框架解析之MvcHandler
从MvcHandler开始 首选MvcHandler显示实现了IHttpHandler接口中的void ProcessRequest(HttpContext context); 外层逻辑: 1.方法参 ...
- show
showproperties thefrm.Controls --显示属性??showmethods thefrm.Menu---显示功能?? showclass "*bitmap*&quo ...
- 打log
如果项目上过线的话,那你一定知道Log是多么重要. 为什么说Log重要呢?因为上线项目不允许你调试,你只能通过Log来分析问题.这时打一手好Log的重要性绝不亚于写一手好代码.项目出问题时,你要能拿出 ...
- 优先级和lisp式前缀表达式
if(f(a,b) > 0) # 1 if(f(a, b>0)) # 2 上面在调用f的时候,1使用括号表明了参数的优先级,不然会出现2这样的情况. 而使用lisp式的前缀表达式则不会有不 ...
- 消息队列msmq
http://q.cnblogs.com/q/26895/ 远程队列必须现在运程服务器上创建. 在 Windows Server 2008 上安装 IIS 服务和 MSMQ 功能后,系统会在 IIS ...
- ORACLE 字符串操作
1 字符串连接 SQL> select 'abc' || 'def' from dual; 'ABC'|------abcdef 2 小写SQL>select lower('ABC01 ...
- 删除数据表和清空数据表的内容(保存表结构)的SHELL脚本
A,删除指定数据库的所有数据表 #!/bin/bash # 删除mysql中所有表 # 示例: # Usage: ./script user password dbnane # Usage: ./sc ...
- [转载]# Ajax异步请求阻塞情况的解决办法
最近使用ExtJs4的mvc模式在开发了在线漫画的后台,因为异步请求比较多,有的回应时间长,有点短.我发现在多次并发的情况下,会造成阻塞的情况.也就是说如果回应时间长的请求还在进行中,短的请求却被挂起 ...