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
#include
#include
#include
#include
#include
#include
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
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
expired_cond_.wait(locker, [
this
]{
return
expired_ ==
true
; });
if
(expired_ ==
true
){
// std::cout << "timer expired!" << std::endl;
try_to_expire_ =
false
;
}
}
}
template
class
... arguments>
void
SyncWait(
int
after, callable&& f, arguments&&... args){
std::function
(std::bind(std::forward
std::this_thread::sleep_for(std::chrono::milliseconds(after));
task();
}
template
class
... arguments>
void
AsyncWait(
int
after, callable&& f, arguments&&... args){
std::function
(std::bind(std::forward
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
#include
#include
#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;
}