天秀代码搬运1:C++ 11异步定时器,可定时异步执行函数

原文地址:https://www.cnblogs.com/gtarcoder/p/4924097.html
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
#include<iostream>

#include<string>

#include<memory>

#include"Timer.h"

using namespace std;

void EchoFunc(std::string&& s) {

	std::cout << "test : " << s << endl;

}

void Add(int a, int b)
{
	std::cout << "a=" << a << " " << "b=" << b <<" "<<"a+b="<<a+b<< endl;
}

int main()
{
	Timer t;

	//周期性执行定时任务 

	t.StartTimer(40, std::bind(EchoFunc, "hello world!"));

	std::this_thread::sleep_for(std::chrono::seconds(4));

	std::cout << "try to expire timer!" << std::endl;

	t.Expire();

	while (true)
	{
		//t.StartTimer(1000, std::bind(EchoFunc, "hello world!"));
		t.StartTimer(1000, std::bind(Add,1,3));
	}


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

猜你喜欢

转载自blog.csdn.net/HW140701/article/details/86655643