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;
}
c++11实现异步定时器的更多相关文章
- boost库学习随记六:使用同步定时器、异步定时器、bind、成员函数回调处理、多线程的同步处理示例等
一.使用同步定时器 这个示例程序通过展示如何在一个定时器执行一个阻塞等待. //makefile #-------------------------------------------------- ...
- 2018.2.11 JS的定时器制作
定时器 1.定时器定义 var time = window.setInterval("执行名词",间隔时间) 关闭定时器 clearInterval(定时器名称) 倒计时定时器 s ...
- 使用boost的deadline_timer实现一个异步定时器
概述 最近在工作上需要用到定时器,然后看到boost里面的deadline_timer可以实现一个定时器,所以就直接将其封装成了ATimer类,方便使用,ATimer有以下优点: 可以支持纳秒.毫秒. ...
- C++11 使用异步编程std::async和std::future
先说明一点:std::asyanc是std::future的高级封装, 一般我们不会直接使用std::futrue,而是使用对std::future的高级封装std::async. 下面分别说一下. ...
- 2015.3.11 VS异步控件及进度条结合应用
1.在Form中添加 指针控件:BackgroundWorker-bgwork:进度条控件progressBar1 以及开始.取消按钮 2.开始按钮启动异步线程 private void button ...
- 11 Windows编程——定时器
周期性的发送WWL_TIMER消息的一个东西,这个周期可以由程序员自己设定.设定周期的数是SetTimer,停止定时器消息发送的函数是:Killximer: 定时器消息的特点: 1.不准确(也就是说, ...
- 2020.11.2 异步IO 协程
异步IO 同步IO在一个线程中,CPU执行代码的速度极快,然而,一旦遇到IO操作,如读写文件.发送网络数据时,就需要等待IO操作完成,才能继续进行下一步操作. 在IO操作的过程中,当前线程被挂起,而其 ...
- 第11章 Windows线程池(1)_传统的Windows线程池
第11章 Windows线程池 11.1 传统的Windows线程池及API (1)线程池中的几种底层线程 ①可变数量的长任务线程:WT_EXECUTELONGFUNCTION ②Timer线程:调用 ...
- CoreAnimation6-基于定时器的动画和性能调优
基于定时器的动画 定时帧 动画看起来是用来显示一段连续的运动过程,但实际上当在固定位置上展示像素的时候并不能做到这一点.一般来说这种显示都无法做到连续的移动,能做的仅仅是足够快地展示一系列静态图片,只 ...
随机推荐
- 【WPF】C#代码动态改变控件的样式
需求:C#代码生成的一组按钮Button需要设置样式. 如果是在XAML中引入样式: <!-- 引入资源 --> <UserControl.Resources> <Res ...
- 【WPF】弹窗定位、弹窗关闭后再打开的报错
需求:点击按钮,打开一个弹窗. // 获得窗体实例 Window window = openDesignViewModel.View as Window; // 这是使用了WAF框架 //Window ...
- Cent OS 6.5下安装gcc-5.3.0
目录: .下载源码包 .安装以前版本的GCC编译器 .文件传输 .熟悉解压命令 .安装流程 .开始安装 .安装必备包之GMP,MPFR,MPC的安装 .继续安装 [1.下载源码包] ...
- Jquery解析json数组字符串
最近在工作中用到了Jquery来解析json字符串,网上解析jquery解析json单个对象的实例不少,但是jquery解析json数组的实例却是不多,下面我举一个简单的例子来跟大家分享与一下,本人水 ...
- drupal 使用步骤
一.安装 二.汉化 ①.下载语言包文件:http://localize.drupal.org/translate/languages/zh-hans ②.将 .po 文件放置到 drupal7/pro ...
- Jqueruy验证 form表单提交之前的中的数据
//---表单提交---- $("#destiation_form").submit(function(){ var from_city_value=$("#from_c ...
- html 块状元素 内联元素
块状元素 address - 地址blockquote - 块引用center - 举中对齐块dir - 目录列表div - 常用块级容易,也是CSS layout的主要标签dl - 定义列表fiel ...
- 从my里调出数据插入到ms2008 骨架 php
<?php $server ="XEJMZWMDIXE9CIJ";//ms,服务器IP地址,如果是本地,可以写成localhost $uid =""; / ...
- php插入htm htm插入php的变量
<?php $file = "ueditor\php\upload\image\*\*.png"; foreach (glob("$file") as $ ...
- -lpthread和-pthread的区别
编译程序包括 预编译, 编译,汇编,链接,包含头文件了,仅能说明有了线程函数的声明, 但是还没有实现, 加上-lpthread是在链接阶段,链接这个库.<stdio.h>等都是静态库,不需 ...