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;
}
时间: 2024-10-15 18:27:50

c++11实现异步定时器的相关文章

boost库学习随记六:使用同步定时器、异步定时器、bind、成员函数回调处理、多线程的同步处理示例等

一.使用同步定时器 这个示例程序通过展示如何在一个定时器执行一个阻塞等待. [cpp] view plaincopy //makefile #---------------------------------------------------------- #makefile helloworld测试用例 # # # # #----------------------------------------------------------- ggg=g++ exe=asiotimer #所有的

2015.3.11 VS异步控件及进度条结合应用

1.在Form中添加 指针控件:BackgroundWorker-bgwork:进度条控件progressBar1 以及开始.取消按钮 2.开始按钮启动异步线程 private void button1_Click(object sender, EventArgs e) { bgwork.WorkerReportsProgress = true; //允许异步控件报告状态 bgwork.WorkerSupportsCancellation = true;//允许终止 bgwork.RunWork

STM32学习笔记11(通用定时器作为输入捕获2)

通用定时器作为输入捕获的使用.我们将用 TIM5 的通道 1 (PA0)来做输入捕获,捕获 PA0 上高电平的脉宽(用 WK_UP 按键输入高电平),通过串口打印高电平脉宽时间 输入捕获简介 输入捕获模式可以用来测量脉冲宽度或者测量频率. STM32 的定时器,除了 TIM6 和 TIM7,其他定时器都有输入捕获功能.STM32 的输入捕获,简单的说就是通过检测 TIMx_CHx 上的边沿信号,在边沿信号发生跳变(比如上升沿/下降沿)的时候,将当前定时器的值(TIMx_CNT)存放到对应的通道的

Lucene系列:(11)异步分页

使用到的jar包,分为4部分: (1)beanutils commons-beanutils-1.9.2.jar commons-collections-3.2.1.jar commons-logging-1.1.1.jar (2)gson gson-2.6.2.jar (3)IK Analyzer IKAnalyzer3.2.0Stable.jar (4)lucene lucene-analyzers-3.0.2.jar lucene-core-3.0.2.jar lucene-highlig

使用boost的deadline_timer实现一个异步定时器

概述 最近在工作上需要用到定时器,然后看到boost里面的deadline_timer可以实现一个定时器,所以就直接将其封装成了ATimer类,方便使用,ATimer有以下优点: 可以支持纳秒.毫秒.秒.分.小时定时. 可以随时停止定时器. 支持单次调用. 因为使用了deadline_timer,所以定时比较准确. ATimer和Qt的QTimer使用方法类似,若没有类似的Timer类,使用最原始的方法,我们的代码可能会是这样的: m_timerThread = std::thread([thi

c++11 使用异步编程std::async和std::future

先说明一点:std::asyanc是std::future的高级封装, 一般我们不会直接使用std::futrue,而是使用对std::future的高级封装std::async. 下面分别说一下. 一.std::async基本用法 std::future可以从异步任务中获取结果,一般与std::async配合使用,std::async用于创建异步任务,实际上就是创建一个线程执行相应任务. std::async就是异步编程的高级封装,封装了std::future的操作,基本上可以代替std::t

CoreAnimation6-基于定时器的动画和性能调优

基于定时器的动画 定时帧 动画看起来是用来显示一段连续的运动过程,但实际上当在固定位置上展示像素的时候并不能做到这一点.一般来说这种显示都无法做到连续的移动,能做的仅仅是足够快地展示一系列静态图片,只是看起来像是做了运动. 我们之前提到过iOS按照每秒60次刷新屏幕,然后CAAnimation计算出需要展示的新的帧,然后在每次屏幕更新的时候同步绘制上去,CAAnimation最机智的地方在于每次刷新需要展示的时候去计算插值和缓冲. 之前,我们解决了如何自定义缓冲函数,然后根据需要展示的帧的数组来

基于定时器的动画和性能调优

摘自:http://www.cocoachina.com/ios/20150106/10839.html 基于定时器的动画 我可以指导你,但是你必须按照我说的做. -- 骇客帝国 在第10章“缓冲”中,我们研究了CAMediaTimingFunction,它是一个通过控制动画缓冲来模拟物理效果例如加速或者减速来增强现实感的东西,那么如果想更加真实地模拟 物理交互或者实时根据用户输入修改动画改怎么办呢?在这一章中,我们将继续探索一种能够允许我们精确地控制一帧一帧展示的基于定时器的动画. 定时帧 动

iOS Core Animation Advanced Techniques(六): 基于定时器的动画和性能调优

基于定时器的动画 我可以指导你,但是你必须按照我说的做. -- 骇客帝国 在第10章“缓冲”中,我们研究了CAMediaTimingFunction,它是一个通过控制动画缓冲来模拟物理效果例如加速或者减速来增强现实感的东西,那么如果想更加真实地模拟 物理交互或者实时根据用户输入修改动画改怎么办呢?在这一章中,我们将继续探索一种能够允许我们精确地控制一帧一帧展示的基于定时器的动画. 定时帧 动画看起来是用来显示一段连续的运动过程,但实际上当在固定位置上展示像素的时候并不能做到这一点.一般来说这种显