C++ 11 实现定时器

用C++写了个定时器。

项目的需求是原来Windows的程序,用到了windows APi的 SetTimerKillTimer 来创建和销毁定时器,现在要移植代码到Linux,实现与其相似的功能。

首先创建一个Timer类,管理单个定时器。

1 typedef std::function<void()> TimerFunc;
 2 
 3 #define TIMER_ID unsigned long
 4 #define INTERVAL unsigned int
 5 
 6 class MyTimer{
 7 public:
 8     MyTimer(TIMER_ID _id, INTERVAL _interval, TimerFunc _func);
 9     void stopTimer();
10     void startTimer();
11     ~MyTimer();
12 private:
13     TIMER_ID m_id;
14     INTERVAL m_interval;
15     bool m_stop;
16     TimerFunc m_func;
17     std::future<int> m_future;
18 };

用一个全局hash表来管理Timer,并定义一个全局的mutex实现线程锁

1 std::unordered_map<TIMER_ID, MyTimer*> TimerMap;
2 std::mutex g_mutex;

定义一个TimerServer类实现接口:

1 class TimerService
 2 {
 3 public:
 4     static TIMER_ID setTimer(INTERVAL _interval, TimerFunc _func);
 5     static void killTimer(TIMER_ID _id);
 6 };
 7 
 8 static TIMER_ID NewTimerID = 0;
 9 
10 TIMER_ID TimerService::setTimer(INTERVAL _interval, TimerFunc _func){
11     MyTimer* pTimer = new MyTimer(NewTimerID, _interval, _func);
12     TimerMap[NewTimerID] = pTimer;
13     pTimer->startTimer();
14     return NewTimerID++;
15 }
16 
17 void TimerService::killTimer(unsigned long _id)
18 {
19     MyTimer* pTimer = TimerMap.at(_id);
20     if (pTimer){
21         pTimer->stopTimer();
22         delete pTimer;
23         TimerMap.erase(_id);
24     }
25 }

Timer内部的方法实现:

1 MyTimer::MyTimer(unsigned long _id, unsigned int _interval, TimerFunc _func)
 2 {
 3     m_id = _id;
 4     m_interval = _interval;
 5     m_func = _func;
 6     m_stop = false;
 7 }
 8 
 9 void MyTimer::startTimer()
10 {
11     m_future = std::async(std::launch::async, [this](){
12         while(true){
13             if(m_stop)
14                 break;
15             std::this_thread::sleep_for(std::chrono::milliseconds(m_interval));
16             std::lock_guard<std::mutex> lock(g_mutex);
17             m_func();
18         }
19         return 0;
20     });
21 }
22 
23 void MyTimer::stopTimer()
24 {
25     m_stop = true;
26     m_future.wait();
27 }
28 
29 MyTimer::~MyTimer()
30 {
31 
32 }

测试:

1 #include <iostream>
 2 #include "mytimer.h"
 3 #include <chrono>
 4 #include <functional>
 5 
 6 using namespace std;
 7 
 8 void printWorld() {
 9     cout << "world" << endl;
10 }
11 
12 class Router{
13 public:
14     void countSelf() {
15         cout << "Count is " << count << endl;
16         count++;
17     }
18 
19     Router(){
20         count = 0;
21         id = TimerService::setTimer(1000, std::bind(&Router::countSelf, this));
22     }
23     ~Router() {
24         TimerService::killTimer(id);
25     }
26 
27 private:
28     unsigned int count;
29     unsigned long id;
30 };
31 
32 int main()
33 {
34     auto l1 = TimerService::setTimer(1000, [](){cout << "hello" << endl;});
35     auto l2 = TimerService::setTimer(1000, std::bind(printWorld));
36     Router *r = new Router;
37 
38     std::this_thread::sleep_for(std::chrono::seconds(3));
39     TimerService::killTimer(l2);
40     delete r;
41     std::this_thread::sleep_for(std::chrono::seconds(5));
42     return 0;
43 }

Github

Edit:

代码做了一些优化,去掉TimerService类,用static替代全局变量

MyTimer.h

1 #ifndef MYTIMER_H
 2 #define MYTIMER_H
 3 
 4 #include <functional>
 5 #include <atomic>
 6 #include <future>
 7 #include <list>
 8 #include <map>
 9 
10 typedef std::function<void()> TimerFunc;
11 
12 #define TIMER_ID unsigned long
13 #define INTERVAL unsigned int
14 #define ERRCOUNT unsigned char
15 
16 class MyTimer{
17 public:
18     MyTimer(TimerFunc _func);
19 
20     static MyTimer* GetInstance(TimerFunc _func);
21     void stopTimer();
22     void startTimer(INTERVAL _interval);
23     void setTimerEnabled(bool _enabled);
24     ~MyTimer();
25 
26 private:
27     TIMER_ID m_id;
28     INTERVAL m_interval;
29     bool m_stop;
30     bool m_enabled;
31     TimerFunc m_func;
32     std::future<int> m_future;
33 
34     static std::map<TIMER_ID, MyTimer*> s_timerMap;
35     static std::mutex s_mutex;
36     static TIMER_ID s_id;
37 
38 };
39 
40 #endif // MYTIMER_H

MyTimer.cpp

1 #include "mytimer.h"
 2 #include <chrono>
 3 #include <thread>
 4 #include <utility>
 5 #include <functional>
 6 
 7 std::map<TIMER_ID, MyTimer*> MyTimer::s_timerMap;
 8 std::mutex MyTimer::s_mutex;
 9 TIMER_ID MyTimer::s_id = 0;
10 
11 MyTimer::MyTimer(TimerFunc _func)
12 {
13     m_id = s_id;
14     m_interval = 0;
15     m_func = _func;
16     m_stop = false;
17     m_enabled = false;
18     s_timerMap[m_id] = this;
19 }
20 
21 MyTimer *MyTimer::GetInstance(TimerFunc _func)
22 {
23     return new MyTimer(_func);
24 }
25 
26 void MyTimer::startTimer(INTERVAL _interval)
27 {
28     m_interval = _interval;
29     m_enabled = true;
30     m_future = std::async(std::launch::async, [this](){
31         while(true){
32             if(m_stop)
33                 break;
34             std::this_thread::sleep_for(std::chrono::milliseconds(m_interval));
35             std::lock_guard<std::mutex> lock(s_mutex);
36             if(m_enabled && !m_stop)
37                 m_func();
38         }
39         return 0;
40     });
41 }
42 
43 void MyTimer::setTimerEnabled(bool _enabled)
44 {
45     46     m_enabled = _enabled;
47 }
48 
49 void MyTimer::stopTimer()
50 {
51     m_stop = true;
52     m_future.wait();
53 }
54 
55 MyTimer::~MyTimer()
56 {
57     if (m_stop == false)
58         stopTimer();
59     if (s_timerMap.find(m_id) != s_timerMap.end())
60         s_timerMap.erase(m_id);
61 }

测试:

1 #include <iostream>
 2 #include "mytimer.h"
 3 #include <chrono>
 4 #include <functional>
 5 
 6 using namespace std;
 7 
 8 void printWorld() {
 9     cout << "world" << endl;
10 }
11 
12 class Router{
13 public:
14     void countSelf() {
15         cout << "Count is " << count << endl;
16         count++;
17     }
18 
19     Router(){
20         count = 0;
21         pTimer = MyTimer::GetInstance(std::bind(&Router::countSelf, this));
22         pTimer->startTimer(500);
23     }
24     ~Router() {
25         pTimer->stopTimer();
26     }
27 
28 private:
29     unsigned int count;
30     MyTimer* pTimer;
31 };
32 
33 int main()
34 {
35     MyTimer* pTimer1;
36     MyTimer* pTimer2;
37     pTimer1 = MyTimer::GetInstance([](){cout << "hello" << endl;});
38     pTimer2 = MyTimer::GetInstance(std::bind(printWorld));
39     pTimer1->startTimer(1000);
40     pTimer2->startTimer(1000);
41     Router *r = new Router;
42     std::this_thread::sleep_for(std::chrono::seconds(2));
43     pTimer2->setTimerEnabled(false);
44     std::this_thread::sleep_for(std::chrono::seconds(3));
45     pTimer2->setTimerEnabled(true);
46     delete pTimer1;
47     delete r;
48     std::this_thread::sleep_for(std::chrono::seconds(5));
49     return 0;
50 }

原文链接: https://www.cnblogs.com/Asp1rant/p/14881089.html

欢迎关注

微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/211367

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年2月13日 上午12:46
下一篇 2023年2月13日 上午12:47

相关推荐