c++11提供了丰富的时间和线程操作函数,比如 std::this_thread::sleep, std::chrono::seconds等。可以利用这些来很方便的实现一个定时器。 
    定时器要求在固定的时间异步执行一个操作,比如boost库中的boost::asio::deadline_timer,以及MFC中的定时器。这里,利用c++11的thread, mutex, condition_variable 来实现一个定时器: 
    定时器要求异步执行任务    ----> 开辟独立的线程 
    定时器要求能够启动和取消 ----> 提供安全的取消操作,使用互斥量和信号量 
    定时器要求每个定时时刻到达的时候执行的任务要尽可能节省时间

实现

  1. #ifndef TIMER_H_
  2. #define TIMER_H_
  3. #include<functional>
  4. #include<chrono>
  5. #include<thread>
  6. #include<atomic>
  7. #include<memory>
  8. #include<mutex>
  9. #include<condition_variable>
  10. class Timer{
  11. public:
  12. Timer() :expired_(true), try_to_expire_(false){
  13. }
  14.  
  15. Timer(const Timer& t){
  16. expired_ = t.expired_.load();
  17. try_to_expire_ = t.try_to_expire_.load();
  18. }
  19. ~Timer(){
  20. Expire();
  21. // std::cout << "timer destructed!" << std::endl;
  22. }
  23.  
  24. void StartTimer(int interval, std::function<void()> task){
  25. if (expired_ == false){
  26. // std::cout << "timer is currently running, please expire it first..." << std::endl;
  27. return;
  28. }
  29. expired_ = false;
  30. std::thread([this, interval, task](){
  31. while (!try_to_expire_){
  32. std::this_thread::sleep_for(std::chrono::milliseconds(interval));
  33. task();
  34. }
  35. // std::cout << "stop task..." << std::endl;
  36. {
  37. std::lock_guard<std::mutex> locker(mutex_);
  38. expired_ = true;
  39. expired_cond_.notify_one();
  40. }
  41. }).detach();
  42. }
  43.  
  44. void Expire(){
  45. if (expired_){
  46. return;
  47. }
  48.  
  49. if (try_to_expire_){
  50. // std::cout << "timer is trying to expire, please wait..." << std::endl;
  51. return;
  52. }
  53. try_to_expire_ = true;
  54. {
  55. std::unique_lock<std::mutex> locker(mutex_);
  56. expired_cond_.wait(locker, [this]{return expired_ == true; });
  57. if (expired_ == true){
  58. // std::cout << "timer expired!" << std::endl;
  59. try_to_expire_ = false;
  60. }
  61. }
  62. }
  63.  
  64. template<typename callable, class... arguments>
  65. void SyncWait(int after, callable&& f, arguments&&... args){
  66.  
  67. std::function<typename std::result_of<callable(arguments...)>::type()> task
  68. (std::bind(std::forward<callable>(f), std::forward<arguments>(args)...));
  69. std::this_thread::sleep_for(std::chrono::milliseconds(after));
  70. task();
  71. }
  72. template<typename callable, class... arguments>
  73. void AsyncWait(int after, callable&& f, arguments&&... args){
  74. std::function<typename std::result_of<callable(arguments...)>::type()> task
  75. (std::bind(std::forward<callable>(f), std::forward<arguments>(args)...));
  76.  
  77. std::thread([after, task](){
  78. std::this_thread::sleep_for(std::chrono::milliseconds(after));
  79. task();
  80. }).detach();
  81. }
  82.  
  83. private:
  84. std::atomic<bool> expired_;
  85. std::atomic<bool> try_to_expire_;
  86. std::mutex mutex_;
  87. std::condition_variable expired_cond_;
  88. };
  89. #endif
  90.  
  91. ////////////////////test.cpp
  92. #include<iostream>
  93. #include<string>
  94. #include<memory>
  95. #include"Timer.hpp"
  96. using namespace std;
  97. void EchoFunc(std::string&& s){
  98. std::cout << "test : " << s << endl;
  99. }
  100.  
  101. int main(){
  102. Timer t;
  103. //周期性执行定时任务
  104. t.StartTimer(1000, std::bind(EchoFunc,"hello world!"));
  105. std::this_thread::sleep_for(std::chrono::seconds(4));
  106. std::cout << "try to expire timer!" << std::endl;
  107. t.Expire();
  108.  
  109. //周期性执行定时任务
  110. t.StartTimer(1000, std::bind(EchoFunc, "hello c++11!"));
  111. std::this_thread::sleep_for(std::chrono::seconds(4));
  112. std::cout << "try to expire timer!" << std::endl;
  113. t.Expire();
  114.  
  115. std::this_thread::sleep_for(std::chrono::seconds(2));
  116.  
  117. //只执行一次定时任务
  118. //同步
  119. t.SyncWait(1000, EchoFunc, "hello world!");
  120. //异步
  121. t.AsyncWait(1000, EchoFunc, "hello c++11!");
  122.  
  123. std::this_thread::sleep_for(std::chrono::seconds(2));
  124.  
  125. return 0;
  126. }

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

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

    一.使用同步定时器 这个示例程序通过展示如何在一个定时器执行一个阻塞等待. //makefile #-------------------------------------------------- ...

  2. 2018.2.11 JS的定时器制作

    定时器 1.定时器定义 var time = window.setInterval("执行名词",间隔时间) 关闭定时器 clearInterval(定时器名称) 倒计时定时器 s ...

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

    概述 最近在工作上需要用到定时器,然后看到boost里面的deadline_timer可以实现一个定时器,所以就直接将其封装成了ATimer类,方便使用,ATimer有以下优点: 可以支持纳秒.毫秒. ...

  4. C++11 使用异步编程std::async和std::future

    先说明一点:std::asyanc是std::future的高级封装, 一般我们不会直接使用std::futrue,而是使用对std::future的高级封装std::async. 下面分别说一下. ...

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

    1.在Form中添加 指针控件:BackgroundWorker-bgwork:进度条控件progressBar1 以及开始.取消按钮 2.开始按钮启动异步线程 private void button ...

  6. 11 Windows编程——定时器

    周期性的发送WWL_TIMER消息的一个东西,这个周期可以由程序员自己设定.设定周期的数是SetTimer,停止定时器消息发送的函数是:Killximer: 定时器消息的特点: 1.不准确(也就是说, ...

  7. 2020.11.2 异步IO 协程

    异步IO 同步IO在一个线程中,CPU执行代码的速度极快,然而,一旦遇到IO操作,如读写文件.发送网络数据时,就需要等待IO操作完成,才能继续进行下一步操作. 在IO操作的过程中,当前线程被挂起,而其 ...

  8. 第11章 Windows线程池(1)_传统的Windows线程池

    第11章 Windows线程池 11.1 传统的Windows线程池及API (1)线程池中的几种底层线程 ①可变数量的长任务线程:WT_EXECUTELONGFUNCTION ②Timer线程:调用 ...

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

    基于定时器的动画 定时帧 动画看起来是用来显示一段连续的运动过程,但实际上当在固定位置上展示像素的时候并不能做到这一点.一般来说这种显示都无法做到连续的移动,能做的仅仅是足够快地展示一系列静态图片,只 ...

随机推荐

  1. 【C#/WPF】.Net生成二维码QRCode的工具

    先马 http://qrcodenet.codeplex.com/ 使用该工具WPF生成二维码的简单例子: 前台XAML准备一个Image控件显示二维码. string qrcodeStr = &qu ...

  2. Java应用程序项目的打包与发行

    Java应用程序项目的打包与发行    这里主要是讲解一下怎样将 Java程序打包成独立运行的exe程序包,以下这种方法应该是最佳的解决方案了.NetDuke的EXE 程序包了是使用这种方案制作的.在 ...

  3. CAS (2) —— Mac下配置CAS到Tomcat(客户端)

    CAS (2) -- Mac下配置CAS到Tomcat(客户端) tomcat版本: tomcat-8.0.29 jdk版本: jdk1.8.0_65 cas版本: cas4.1.2 cas-clie ...

  4. KafkaStream时间戳问题CreateTime = -1引起的程序中断

    Exception in thread "app-8835188a-e0a0-46da-ac2a-6820ec197628-StreamThread-1" org.apache.k ...

  5. JavaScriptSerializer 时间格式化

    时间格式化 Model m = , Dt = DateTime.Now }; JavaScriptSerializer js = new JavaScriptSerializer(); string ...

  6. 【C】——压缩字符串

    编一个函数,输入一个字符串,要求做一个新字符串,把其中所有的一个或多个连续的空白字符都压缩为一个空格.这里所说的空白包括空格.'\t'.'\n'.'\r'.例如原来的字符串是: This Conten ...

  7. l2正则化

    在机器学习中,无论是分类还是回归,都可能存在由于特征过多而导致的过拟合问题.当然解决的办法有 (1)减少特征,留取最重要的特征. (2)惩罚不重要的特征的权重. 但是通常情况下,我们不知道应该惩罚哪些 ...

  8. jquery 自动完成 Autocomplete插件汇总

    1. jQuery Autocomplete Mod jQuery Autcomplete插件.能够限制下拉菜单显示的结果数. 主页:http://www.pengoworks.com/worksho ...

  9. 消息中间件系列之Java API操作ActiveMQ

    一.依赖 <dependency> <groupId>org.apache.activemq</groupId> <artifactId>activem ...

  10. 关于Struts2的action的execute方法

    这个方法必须要有一个String类型的返回值,所以如果写很多if else的话,记得要在最后加一个else,就是无论如何就会放回一个字符串,否则编译会报错,在execute方法名字下面有红线.