c++11提供了丰富的时间和线程操作函数,比如 std::this_thread::sleep, std::chrono::seconds等。可以利用这些来很方便的实现一个定时器。
定时器要求在固定的时间异步执行一个操作,比如boost库中的boost::asio::deadline_timer,以及MFC中的定时器。这里,利用c++11的thread, mutex, condition_variable 来实现一个定时器:
定时器要求异步执行任务 ----> 开辟独立的线程
定时器要求能够启动和取消 ----> 提供安全的取消操作,使用互斥量和信号量
定时器要求每个定时时刻到达的时候执行的任务要尽可能节省时间
实现
#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; }
时间: 2024-10-15 18:27:50