为了账号安全,请及时绑定邮箱和手机立即绑定

如何使用C++11实现跨平台的定时器timer

如何使用C++11实现跨平台的定时器timer

C++
Cats萌萌 2018-07-04 10:09:31
查看完整描述

2 回答

?
梵蒂冈之花

TA贡献1900条经验 获得超5个赞

一个Timer的实现需要具备以下几个行为:

StartTimer(Interval, ExpiryAction)

注册一个时间间隔为 Interval 后执行 ExpiryAction 的定时器实例,其中,返回 TimerId 以区分在定时器系统中的其他定时器实例。

StopTimer(TimerId)

根据 TimerId 找到注册的定时器实例并执行 Stop 。

PerTickBookkeeping()

在一个 Tick 时间粒度内,定时器系统需要执行的动作,它最主要的行为,就是检查定时器系统中,是否有定时器实例已经到期。

具体的代码实现思路就是:

StartTimer的时候,把 当前时间 + Interval
作为key放入一个容器,然后在Loop的每次Tick里,从容器里面选出一个最小的key与当前时间比较,如果key小于当前时间,则这个key代表的
timer就是expired,需要执行它的ExpiryAction(一般为回调)。

这里有两个实现的细节:

获取当前时间

包含时间精度,使用系统时间还是CPU时间(asio里的deadline_timer和steady_timer的区别)
常用的API是:
Windows: QueryPerformanceFrequency() 和 QueryPerformanceCounter()
Linux: clock_gettime()
OSX: gettimeofday()或者mach_absolute_time()
当然在C++11里也可以偷懒使用chrono的high_resolution_clock std::chrono::high_resolution_clock

2.timer容器的选择

容器应该能够在很短的时间内找到MinValue
最小堆的find-min复杂度是O(1),所以蛮受人喜欢的
STL里提供有堆的API,make_heap, push_heap, pop_heap, sort_heap

3. PerTickBookkeeping是放在主循环线程还是另起线程

另起线程需要做好线程间通信,asio和skynet有单独的timer线程

查看完整回答
反对 回复 2018-07-31
  • 2 回答
  • 0 关注
  • 1836 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信