定时器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服务,分为同步和异步两种类型,一般执行步骤较 ...
随机推荐
- 编程基础知识——C++能不能支持Java和ObjC的反射?
C++能不能支持Java和ObjC的反射? 要回答这个问题.首先我们要清楚什么是反射.什么是反射? 教科书的解释我就不说了,(^o^)事实上我也记不得.实际开发应用的反射就是在没有某个类型的头文件或者 ...
- Android4.0.4-在build.prop中添加属性的方法【转】
本文转载自:http://blog.csdn.net/imyfriend/article/details/8939964 1.在*.rc文件中用setprop添加,例如在源码android4.0\sy ...
- netpbm开机logo制作工作【转】
本文转载自: http://www.fx114.net/qa-19-74437.aspx
- Quartz实例:quartz定时任务代码示例
转自:http://www.blogchong.com/post/96.html quartz定时任务调度框架,使用实例. Job类://即实际调度任务实现 . package net.csdn.ed ...
- 利用ajax,canvas实现的测试php程序占用内存的代码
receive.php <?php $array["time"]=time();$array["memory"]=memory_get_usage();e ...
- expdp通过dblink远端导出
环境说明: db62是源端 rac数据库 dw03为需要导入的目标端数据库单机,实例名,服务名,字符串名都为dw03 数据库版本:11.2.0.4 操作系统:rehat 6.7 1.创建dblink ...
- MAVEN 杂记
MAVEN中央仓库 http://repo.maven.apache.org/maven2http://repo1.maven.org/maven2/http://mvnrepository.com/ ...
- 动画库animate.css的用法
简介 animate.css是一个来自国外的 CSS3 动画库,它预设了引起弹跳(bounce).摇摆(swing).颤抖(wobble).抖动(shake).闪烁(flash).翻转(flip).旋 ...
- Windows Phone - 按钮/button 控件
System.Windows.Controls.Button button控件一.button控件的各种样式的展示可以通过 …… 来给控件定义公共的样式调用样式的方法:在Button控件上添加样式 ...
- svn SSL 错误:Key usage violation in certificate has been detected
CentOS/RHEL yum 安装的 subversion 是 1.6.11 版本,连VisualSVN服务器时会有"Key usage violation"的错误 将subve ...