c++11实现异步定时器

    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;
}

 

posted @ 2015-10-30 18:18  农民伯伯-Coding  阅读(31246)  评论(13编辑  收藏  举报