实现定时器管理类

一、定时器的用途

定时器在各种通信中有重要的用途。

二、定时器要实现的功能

根据指定的时间间隔产生定时器事件,并达到指定的精度。精度一般由定时器的采样精度相关,也就是和定时器硬件有关。在普通PC中,可以使用多媒体定时器获得10微秒以上的精度。

三、  C++中实现定时器的关键

C++中实现定时器有几个问题要解决:

1、  如何在一个类中管理多个定时器

常见的使用方式中,定时器是一个事件ID和定时间隔的的“键—值”对。CMap是一个dictionary collection class,采用哈希表查找方式来定位,速度十分快,可以尽可能少影响定位精度。但是光保存一个定时间隔键值对还不行,因为不知道当前的定时器计数值(旧preTicks),故还要一个CMap来保存当前ticks

因此一个定时器对应CMap中的一个“键—值”对。要管理这些定时器,只需要在线程函数中轮询当前定时器的nowTicks,并取得触发间隔elapseTicks,通过比较nowTicks – preTicks > elapseTicks 判断是否到了临界点,掌握定时事件触发时机。

这些工作全由定时器管理类来调度。

2、  使用者(类)应该如何接受定时器事件

可以利用事件或者C++中的虚函数的方式来让使用者(类)接受定时器触发事件,即处理定时器事件的函数被调用。我使用C++抽象类来完成这个工作。

即定义一个定时器事件抽象类,这个抽象类的实现类要成为定时器类的成员变量。当线程判断到定时器触发时,调用这个抽象类的事件处理函数(根据虚拟函数机制的了解,实际调用的实现类的处理函数)。

从上可以看出,如果使用者(类)要用定时器,必须实现定时器抽象类。

3、  谁来启动定时器线程,使用者(类)如何使用定时器管理类来定时。

当然应该由定时器管理类来管理定时线程的启动。使用者要使用定时,必须先实现定时器抽象类,并创建定时器管理类的一个实例,作为其成员变量。

四、  实现

()定义定时器抽象类

class ITimerEvent 

{

public:

         ITimerEvent();

         virtual ~ITimerEvent();

         void virtual OnTimer(UINT nIDEvent)=0;

};

()管理类

class CManTimer

{

public:

         CManTimer(ITimerEvent* pEvent);

 

         ITimerEvent* m_pTimerEvent;

 

         virtual ~CManTimer();

 

         void SetTimer(UINT nIDEvent, LARGE_INTEGER nElapse);

 

         void KillTimer(int nIDEvent);

 

         bool Start();

 

         static DWORD WINAPI ThreadProc(LPVOID lpParameter );

 

         HANDLE m_hMutex;

         HANDLE m_hThread;

         DWORD m_dwThreadId;

 

         BOOL Lock(DWORD dwMilliSec = INFINITE)

         {

                  if( WaitForSingleObject(m_hMutex,dwMilliSec) == WAIT_OBJECT_0)

                            return TRUE;

                   return FALSE;

         }

         BOOL Unlock(DWORD dwMilliSec = INFINITE)

         {

                   return ReleaseMutex(m_hMutex);

         }

         void Destory();

         void TimerProc();

 

private:

         CMap<UINT,UINT,LARGE_INTEGER,LARGE_INTEGER> m_ElapseMap;

         CMap<UINT,UINT,LARGE_INTEGER,LARGE_INTEGER> m_TickMap;

}

 

以下介绍几个关键成员函数的实现:

void CManTimer::SetTimer(UINT nIDEvent, LARGE_INTEGER nElapse)

{

         Lock();

         m_ElapseMap.SetAt(nIDEvent, nElapse);

         LARGE_INTEGER nCurrentTicks = 0;

         QueryPerformanceCounter(&nCurrentTicks);

         m_TickMap.SetAt(nIDEvent, nCurrentTicks);

         Unlock();

}

 

void CManTimer::KillTimer(int nIDEvent)

{

         Lock();

         m_ElapseMap.RemoveKey(nIDEvent);

         m_TickMap.RemoveKey(nIDEvent);

         Unlock();

}

 

DWORD WINAPI ThreadProc(LPVOID lpParameter )

{

         CManTimer* pManTimer = (CManTimer*) lpParameter;

         pManTimer->TimerProc();

         return 0;

}

 

void CManTimer::TimerProc()

{

       while(1)

       {

              if(!m_bContinue)

              {

                     ExitThread(0);

              }

              try

              {

                     POSITION pos = m_ElapseMap.GetStartPosition();

                     UINT nIDEvent;

                     LARGE_INTEGER nElapse;

                     LARGE_INTEGER dTicks;

                     while (pos != NULL)

                     {

                            m_ElapseMap.GetNextAssoc( pos, nIDEvent, nElapse );

                            m_TickMap.Lookup(nIDEvent,dTicks);

 

                            LARGE_INTEGER nCurrentTicks = 0;

                            QueryPerformanceCounter(&nCurrentTicks);

 

                            if(nCurrentTicks - dTicks > nElapse)

                            {

                                   m_pTimerEvent->OnTimer(nIDEvent);

                                   SetTimer(nIDEvent,nElapse);

                            }

                           

                     }

              }

              catch ( ...) {

                     TRACE("ManTimer Exception/n");

              }

       }

}

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值