定时器SDK
定时器是一切SDK的根本,欲写SDK必先确定定时器,定时器效率的高低决定着SDK函数的效率,下面是我个人写的Linux C++服务器端进程SDK中的定时器,部分参照了ACE和RocketMQ定时器的思想,欢迎大家拍砖,一起改进,共同进步。
#ifndef _TIME_THREAD_H
#define _TIME_THREAD_H
#include <list>
#include <map>
class TimerHandler
{
public:
TimerHandler()
{
}
virtual ~TimerHandler()
{
}
virtual void OnTimeOut(unsigned int timerID,void * pOtherArg) = 0;
};
typedef struct tagTimerlnfo
{
unsigned int id;
unsigned int elapse;
int outTime;// 初始化可以为负数,这样就可以延迟启动了
bool persistent;
TimerHandler * pTimerHandler;
void * pOtherArg;
}TimerInfo;
class TimerThread
{
public:
TimerThread();
~TimerThread();
void Start();
void Close();
unsigned int RegisterTimer(unsigned int initialDelay, unsigned int elapse, TimerHandler *pHandler, void * pOtherArg, bool persistent = true);
bool UnRegisterTimer(unsigned int timerId);
bool ResetTimer(unsigned int timerId);
bool IsRunning(){return m_bIsRunning;}
private:
void CheckTimeOut(unsigned int elapse, std::list<TimerInfo>& timerList, int& minWaitTime);
unsigned int GetNextTimerID();
static void* ThreadRoute(void* pArg);
private:
unsigned int s_nextTimerID;
std::map<unsigned int, TimerInfo> m_timers;
pthread_mutex_t m_mutex;
pthread_mutex_t m_startMutex;
pthread_cond_t m_cond;
bool m_bClosed;
bool m_bIsRunning;
pthread_t m_threadId;
};
#endif
#include <string.h>
#include <errno.h>
#include "log.h"
#include "common.h"
#include "TimeThread.h"
TimerThread::TimerThread():m_bClosed(false)
{
s_nextTimerID = 0;
pthread_cond_init(&m_cond,NULL);
pthread_mutex_init(&m_mutex,NULL);
pthread_mutex_init(&m_startMutex,NULL);
m_bIsRunning = false;
}
TimerThread::~TimerThread()
{
pthread_cond_destroy(&m_cond);
pthread_mutex_destroy(&m_mutex);
pthread_mutex_destroy(&m_startMutex);
}
void* TimerThread::ThreadRoute(void* pArg)
{
TimerThread *pTimerThread = (TimerThread*)pArg;
unsigned long long lastCheckTime = GetCurrentTimeMillis();
unsigned long long currentCheckTime = lastCheckTime;
int delayTime = 0;
std::list<TimerInfo> timerList;
while (!pTimerThread->m_bClosed)
{
currentCheckTime = GetCurrentTimeMillis();
unsigned int elapse = (unsigned int)(currentCheckTime - lastCheckTime);
timerList.clear();
pTimerThread->CheckTimeOut(elapse,timerList,delayTime);
if (!timerList.empty())
{
std::list<TimerInfo>::iterator it = timerList.begin();
for (; it != timerList.end(); it++)
{
it->pTimerHandler->OnTimeOut(it->id,it->pOtherArg);
//外部释放
/*
if (it->persistent == false)
{
delete it->pTimerHandler;
}
*/
}
}
unsigned long long checkEndTime = GetCurrentTimeMillis();
lastCheckTime = currentCheckTime;
int sleepTime = delayTime - (int)(checkEndTime -currentCheckTime);
if (sleepTime <= 0)
{
sleepTime = 0;
}
else
{
//usleep(sleepTime * 1000);
//struct timespec tv;
//tv.tv_sec = sleepTime / 1000;
//tv.tv_nsec = (sleepTime % 1000) * 1000000;
//nanosleep(&tv, 0);
pthread_mutex_lock(&pTimerThread->m_mutex);
struct timespec abstime = CalcAbsTime(sleepTime);
pthread_cond_timedwait(&pTimerThread->m_cond, &pTimerThread->m_mutex, &abstime);
pthread_mutex_unlock(&pTimerThread->m_mutex);
}
}
pTimerThread->m_bIsRunning = false;
return 0;
}
void TimerThread::Start()
{
pthread_mutex_lock(&m_startMutex);//同一个定时器避免启动两次
if (!m_bIsRunning)
{
pthread_attr_t attr;
int retcode = 0;
retcode = pthread_attr_init(&attr);
if(retcode != 0)
{
pthread_mutex_unlock(&m_startMutex);
nDebugLog(LOG_PRIORITY_ERROR, "pthread_attr_init failed:%s!",strerror(errno));
return;
}
pthread_t id;
retcode = pthread_create(&id, &attr, ThreadRoute, (void *)this);
if(retcode != 0)
{
pthread_mutex_unlock(&m_startMutex);
nDebugLog(LOG_PRIORITY_ERROR, "pthread_create failed:%s!",strerror(errno));
return;
}
m_threadId = id;
pthread_attr_destroy(&attr);
m_bIsRunning = true;
}
pthread_mutex_unlock(&m_startMutex);
}
void TimerThread::Close()
{
m_bClosed = true;
pthread_mutex_lock(&m_mutex);
pthread_cond_signal(&m_cond);
pthread_mutex_unlock(&m_mutex);
pthread_join(m_threadId, NULL);
}
void TimerThread::CheckTimeOut(unsigned int elapse, std::list<TimerInfo> &timerList, int& minWaitTime)
{
int tmpWait = 0;
minWaitTime = 0;
pthread_mutex_lock(&m_mutex);
if (!m_timers.empty())
{
std::map<unsigned int, TimerInfo>::iterator it = m_timers.begin();
while (it != m_timers.end())
{
it->second.outTime += elapse;
tmpWait = it->second.outTime - int(it->second.elapse);
if (tmpWait >= 0)
{
timerList.push_back(it->second);
if (it->second.persistent)
{
it->second.outTime = 0;
++it;
}
else
{
m_timers.erase(it++);
}
}
else
{
tmpWait = tmpWait * -1;
if (minWaitTime == 0)
{
minWaitTime = tmpWait;
}
else if (minWaitTime > tmpWait)
{
minWaitTime = tmpWait;
}
++it;
}
}
}
else
{
pthread_cond_wait(&m_cond, &m_mutex);
}
pthread_mutex_unlock(&m_mutex);
}
unsigned int TimerThread::RegisterTimer(unsigned int initialDelay,unsigned int elapse, TimerHandler *pHandler, void * pOtherArg, bool persistent)
{
TimerInfo info;
info.elapse = elapse;
info.outTime = 0-initialDelay;
info.pTimerHandler = pHandler;
info.persistent = persistent;
info.pOtherArg = pOtherArg;
pthread_mutex_lock(&m_mutex);
info.id = GetNextTimerID();
m_timers[info.id] = info;
pthread_cond_signal(&m_cond);
pthread_mutex_unlock(&m_mutex);
return info.id;
}
bool TimerThread::UnRegisterTimer(unsigned int timerId)
{
bool result = false;
pthread_mutex_lock(&m_mutex);
std::map<unsigned int, TimerInfo>::iterator it = m_timers.find(timerId);
if (it != m_timers.end())
{
m_timers.erase(it);
result = true;
}
pthread_mutex_unlock(&m_mutex);
return result;
}
bool TimerThread::ResetTimer(unsigned int timerId)
{
bool result = false;
pthread_mutex_lock(&m_mutex);
std::map<unsigned int, TimerInfo>::iterator it = m_timers.find(timerId);
if (it != m_timers.end())
{
if (it->second.persistent)
{
it->second.outTime = it->second.elapse;
}
else
{
it->second.outTime = 0;
}
result = true;
}
pthread_mutex_unlock(&m_mutex);
return result;
}
unsigned int TimerThread::GetNextTimerID()
{
if (s_nextTimerID > 10000000)
{
s_nextTimerID = 0;
}
else
{
++s_nextTimerID;
}
return s_nextTimerID;
}
定时器SDK的更多相关文章
- 11-ESP8266 SDK开发基础入门篇--软硬件定时器
https://www.cnblogs.com/yangfengwu/p/11094009.html 定时器有两种,软件定时器和硬件定时器 软件定时器就是靠里面的任务延时实现的,,这样的定时器其实延时 ...
- 项目总结[2]_svg+ajax+webservice+pSpace sdk实现实时数据的web展示
1.使用svg实现组态画面和动态数据展示 通过js的定时器调用webservice方法获取数据后更新节点数据 /// <summary>启动定时刷新</summary> fun ...
- [nRF51822] 3、 新年也来个总结——图解nRF51 SDK中的Button handling library和FIFO library
:本篇是我翻译并加入自己理解的nRF51 SDK中按钮相关操作的库和先进先出队列库.虽然是nRF51的SDK,但是通过此文你将更多地了解到在BSP(板级支持)上层嵌入式程序或OS的构建方法. 1.按钮 ...
- android 定时器AlarmManager
1.android中通常是使用AlarmManager来定时启动一个单次或重复多次操作的.具体的说就是我们通过AlarmManager设定一个时间和注册一个intent到系统中,然后在该时间到来时,系 ...
- Android中直播视频技术探究之---采集摄像头Camera视频源数据进行推流(采用金山云SDK)
一.前言 在之前已经详细介绍了Android中的一种视频数据源:Camera,不了解的同学可以点击进入:Android中Camera使用详解 ,在这篇文章中我们介绍了如何采集摄像头的每一帧数据,然后进 ...
- android 定时器的使用
1.android中通常是使用AlarmManager来定时启动一个单次或重复多次操作的.具体的说就是我们通过AlarmManager设定一个时间和注册一个intent到系统中,然后在该时间到来时,系 ...
- Android之AlarmManager(全局定时器/闹钟)指定时长或以周期形式执行某项操作
1.AlarmManager,顾名思义,就是“提醒”,是Android中常用的一种系统级别的提示服务,可以实现从指定时间开始,以一个固定的间隔时间执行某项操作,所以常常与广播(Broadcast)连用 ...
- 基于百度定位SDK的定位服务的实现
转载请标明出处:http://blog.csdn.net/android_ls/article/details/10179013 一.定位模块的需求:我们想知道使用我们应用的用户的大概位置,每隔五分钟 ...
- ArcGIS Runtime SDK for Android开发之调用GP服务(异步调用)
一.背景说明 通过调用GP服务,Android客户端也能实现专业的.复杂的GIS分析处理功能,从而增加应用的实用价值. ArcGIS Server发布的GP服务,分为同步和异步两种类型,一般执行步骤较 ...
随机推荐
- MySQL数据库——存储和函数
一.存储过程1 基本语法CREATE PROCEDURE sp_name ([proc_parameter[,...]]) [characteristic ...] routine_body 格式[I ...
- luogu2441 角色属性树
题目大意:维护一个可查询.修改的树,查询的是一个节点的:离它距离最近的.组成两个节点Key值的质因数存在交集的.祖先节点:修改是修改一个节点的key值. 如果组成两个Key值的质因数存在交集,则两个数 ...
- Adding a view
在添加View之前,之前的页面是下面这个样子,需要注意的是浏览器标题,以及浏览器的内容 https://docs.asp.net/en/latest/tutorials/first-mvc-app/a ...
- Eddy's picture
Eddy's picture Time Limit : 2000/1000ms (Java/Other) Memory Limit : 65536/32768K (Java/Other) Tota ...
- Hdu-6230 2017CCPC-哈尔滨站 A.Palindrome Manacher 主席树
题面 题意:给你一个字符串,问你满足s[i]=s[2n-i]=s[2n+i-2]的子串(这子串长度为3n-2)有多少个,原字符串长度<=5e5 题解:对于这种子串,其实要满足2个回文,跑过一次M ...
- Hadoop MapReduce编程 API入门系列之MapReduce多种输入格式(十七)
不多说,直接上代码. 代码 package zhouls.bigdata.myMapReduce.ScoreCount; import java.io.DataInput; import java.i ...
- Pinpoint 监控
####Hbase数据################ 参考: 然而没有卵用: https://blog.csdn.net/iamlihongwei/article/details/52882749? ...
- P1629 邮递员送信(未完成)
题目描述 有一个邮递员要送东西,邮局在节点1.他总共要送N-1样东西,其目的地分别是2~N.由于这个城市的交通比较繁忙,因此所有的道路都是单行的,共有M条道路,通过每条道路需要一定的时间.这个邮递员每 ...
- hdu1811 Rank of Tetris 拓扑排序+并查集
这道题是拓扑排序和并查集的综合运用. 由于排行榜是一种从高到低的排序.所以在拓扑排序的时候,如果有一次加入的入度为零的点数大于1,就有变得不确定了(UNCERTAIN). 由于只有一棵树,当树的数量大 ...
- echarts 圆形图、柱状图
首先引入echarts的js包 <script type="text/javascript" src="js/esl.js"></script ...