用C++写了个定时器。
项目的需求是原来Windows的程序,用到了windows APi的 SetTimer 和 KillTimer 来创建和销毁定时器,现在要移植代码到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 }
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 }