zoukankan      html  css  js  c++  java
  • 定时器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;
    }

  • 相关阅读:
    bootstrap模态框手动开启关闭与设置点击外部不关闭
    mybatis的增删改查返回值小析(六)
    mac安装python本版管理工具pyenv
    taro 编译 建议修改:使用循环的 index 变量作为 key 是一种反优化
    taro-多个input同一个事件处理
    python初探(01D) line 2 SyntaxError: Non-ASCII character 'xe8' 报错
    taro父、子组件通信
    taro---image引入图片
    webpack(五)---模块热替换
    webpack(四)---开发系列
  • 原文地址:https://www.cnblogs.com/guoyinglin/p/4848701.html
Copyright © 2011-2022 走看看