定时器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;
}

时间: 2024-10-12 16:32:09

定时器SDK的相关文章

Android零基础入门第60节:日历视图CalendarView和定时器Chronometer

原文:Android零基础入门第60节:日历视图CalendarView和定时器Chronometer 上一期学习了AnalogClock.DigitalClock和TextClock时钟组件,本期继续来学习日历视图CalendarView和定时器Chronometer. 一.CalendarView 日历视图(CalendarView)可用于显示和选择日期,用户既可选择一个日期,也可通过触 摸来滚动日历.如果希望监控该组件的日期改变,则可调用CalendarView的 setOnDateCha

[nRF51822] 3、 新年也来个总结——图解nRF51 SDK中的Button handling library和FIFO library

:本篇是我翻译并加入自己理解的nRF51 SDK中按钮相关操作的库和先进先出队列库.虽然是nRF51的SDK,但是通过此文你将更多地了解到在BSP(板级支持)上层嵌入式程序或OS的构建方法. 1.按钮相关操作库 按键管理程序是通过GPIO事务和事件管理程序来检测一个按钮是否被按下的.当然,其中也做了消抖的工作——在GPIOTE事件中启动一个定时器用来延时一段时间,当该定时器失效后如果按钮仍然处于按下状态,则会产生一个按钮事件.如果在延时的过程中又有一个新的GPIOTE,那么这个定时器会重新被启动

定时器(api)

定时器 壹佰软件开发小组  整理编译   Microsoft Windows定时器是一种输入设备,它周期性地在每经过一个指定的时间间隔后就通知应用程序一次.您的程序将时间间隔告诉Windows,例如「每10秒钟通知我一声」,然后Windows给您的程序发送周期性发生的WM_TIMER消息以表示时间到了. 初看之下,Windows定时器似乎不如键盘和鼠标设备重要,而且对许多应用程序来说确实如此.但是,定时器比您可能认为的要重要得多,它不只用于计时程序,比如出现在工具列中的Windows时钟和这一章

项目总结[2]_svg+ajax+webservice+pSpace sdk实现实时数据的web展示

1.使用svg实现组态画面和动态数据展示 通过js的定时器调用webservice方法获取数据后更新节点数据 /// <summary>启动定时刷新</summary> function Start() { InitSvgElement(); this.timer = setInterval("GetTagValues()", 1000); } /// <summary>启动定时刷新</summary> function Stop() {

79.ZYNQ内部私有定时器中断

上篇文章实现了了PS接受来自PL的中断,本片文章将在ZYNQ的纯PS里实现私有定时器中断.每个一秒中断一次,在中断函数里计数加1,通过串口打印输出. *本文所使用的开发板是Miz702(兼容zedboard) PC 开发环境版本:Vivado 2015.2 Xilinx SDK 2015.2* 中断原理 中断对于保证任务的实时性非常必要,在ZYNQ里集成了中断控制器GIC(Generic Interrupt Controller).GIC可以接受I/O外设中断IOP和PL中断,将这些中断发给CP

android 定时器的使用

1.android中通常是使用AlarmManager来定时启动一个单次或重复多次操作的.具体的说就是我们通过AlarmManager设定一个时间和注册一个intent到系统中,然后在该时间到来时,系统为我们发送一个广播,即执行我们设定的Intent(要执行的操作),通常我们使用 PendingIntent来实现“要执行的操作”,PendingIntent可以理解为Intent的封装包,简单的说就是将来要执行的Intent操作.他们的区别是:在使用Intent的时候,我们还需要在执行startA

android中使用百度定位sdk实时的计算移动距离

前段时间因为项目需求,通过百度定位adk写了一个实时更新距离的程序(类似大家坐的士时,车上的里程表),遇到很多技术点,总结了一下发表出来和大家相互学习.直接要求定位具体的位置应该是不难的,只需要引入百度定位adk,并配置相关参数就可以完成,显示百度地图也类似,但是如果需要不断的实时显示移动距离,GPS定位从一个点,到第二个点,从第二个点,到第三个点,从第三个点......,移动距离是多少呢?不得不说,要实现这种需求的确存在一定的难度. 目标:使用百度定位sdk开发实时移动距离计算功能,根据经纬度

Android中的定时器AlarmManager

在Android上常用的定时器有两种,一种是Java.util.Timer,一种就是系统的AlarmService AlarmManager的作用文档中的解释是:在特定的时刻为我们广播一个指定的Intent.简单的说就是我们设定一个时间,然后在该时间到来时,AlarmManager为我们广播一个我们设定的Intent,常用方法有五个: (1)set(int type,long startTime,PendingIntent pi): 该方法用于设置一次性闹钟,第一个参数表示闹钟类型,第二个参数表

步步为营_Android开发课[33]_用户界面之AlarmManager(全局定时器)

Focus on technology, enjoy life!-- QQ:804212028 浏览链接:http://blog.csdn.net/y18334702058/article/details/44624305 主题:用户界面之AlarmManager(全局定时器) - AlarmManager的作用: AlarmManager对象配合Intent使用,可以定时的开启一个Activity,发送一个BroadCast,或者开启一个Service. AlarmManager的常用方法有三