c++11实现异步定时器
c++11提供了丰富的时间和线程操作函数,比如 std::this_thread::sleep, std::chrono::seconds等。可以利用这些来很方便的实现一个定时器。
定时器要求在固定的时间异步执行一个操作,比如boost库中的boost::asio::deadline_timer,以及MFC中的定时器。这里,利用c++11的thread, mutex, condition_variable 来实现一个定时器:
定时器要求异步执行任务 ----> 开辟独立的线程
定时器要求能够启动和取消 ----> 提供安全的取消操作,使用互斥量和信号量
定时器要求每个定时时刻到达的时候执行的任务要尽可能节省时间
实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 | #ifndef TIMER_H_ #define TIMER_H_ #include<functional> #include<chrono> #include<thread> #include<atomic> #include<memory> #include<mutex> #include<condition_variable> class Timer{ public : Timer() :expired_( true ), try_to_expire_( false ){ } Timer( const Timer& t){ expired_ = t.expired_.load(); try_to_expire_ = t.try_to_expire_.load(); } ~Timer(){ Expire(); // std::cout << "timer destructed!" << std::endl; } void StartTimer( int interval, std::function< void ()> task){ if (expired_ == false ){ // std::cout << "timer is currently running, please expire it first..." << std::endl; return ; } expired_ = false ; std::thread([ this , interval, task](){ while (!try_to_expire_){ std::this_thread::sleep_for(std::chrono::milliseconds(interval)); task(); } // std::cout << "stop task..." << std::endl; { std::lock_guard<std::mutex> locker(mutex_); expired_ = true ; expired_cond_.notify_one(); } }).detach(); } void Expire(){ if (expired_){ return ; } if (try_to_expire_){ // std::cout << "timer is trying to expire, please wait..." << std::endl; return ; } try_to_expire_ = true ; { std::unique_lock<std::mutex> locker(mutex_); expired_cond_.wait(locker, [ this ]{ return expired_ == true ; }); if (expired_ == true ){ // std::cout << "timer expired!" << std::endl; try_to_expire_ = false ; } } } template<typename callable, class ... arguments> void SyncWait( int after, callable&& f, arguments&&... args){ std::function<typename std::result_of<callable(arguments...)>::type()> task (std::bind(std::forward<callable>(f), std::forward<arguments>(args)...)); std::this_thread::sleep_for(std::chrono::milliseconds(after)); task(); } template<typename callable, class ... arguments> void AsyncWait( int after, callable&& f, arguments&&... args){ std::function<typename std::result_of<callable(arguments...)>::type()> task (std::bind(std::forward<callable>(f), std::forward<arguments>(args)...)); std::thread([after, task](){ std::this_thread::sleep_for(std::chrono::milliseconds(after)); task(); }).detach(); } private : std::atomic< bool > expired_; std::atomic< bool > try_to_expire_; std::mutex mutex_; std::condition_variable expired_cond_; }; #endif ////////////////////test.cpp #include<iostream> #include<string> #include<memory> #include"Timer.hpp" using namespace std; void EchoFunc(std:: string && s){ std::cout << "test : " << s << endl; } int main(){ Timer t; //周期性执行定时任务 t.StartTimer(1000, std::bind(EchoFunc, "hello world!" )); std::this_thread::sleep_for(std::chrono::seconds(4)); std::cout << "try to expire timer!" << std::endl; t.Expire(); //周期性执行定时任务 t.StartTimer(1000, std::bind(EchoFunc, "hello c++11!" )); std::this_thread::sleep_for(std::chrono::seconds(4)); std::cout << "try to expire timer!" << std::endl; t.Expire(); std::this_thread::sleep_for(std::chrono::seconds(2)); //只执行一次定时任务 //同步 t.SyncWait(1000, EchoFunc, "hello world!" ); //异步 t.AsyncWait(1000, EchoFunc, "hello c++11!" ); std::this_thread::sleep_for(std::chrono::seconds(2)); return 0; } |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】凌霞软件回馈社区,携手博客园推出1Panel与Halo联合会员
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步