概述

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

  1. 可以支持纳秒、毫秒、秒、分、小时定时。
  2. 可以随时停止定时器。
  3. 支持单次调用。
  4. 因为使用了deadline_timer,所以定时比较准确。

ATimer和Qt的QTimer使用方法类似,若没有类似的Timer类,使用最原始的方法,我们的代码可能会是这样的:

m_timerThread = std::thread([this]
{
while (!m_bThreadStoped)
{
++m_sleepCount;
Sleep(SLEEP_DURATION_TIME); if (m_sleepCount == m_sleepAllCount)
{
m_sleepCount = 0;
doSomeThing();
}
}
});

若使用QTimer的话,书写是这样的:

QTimer *timer = new QTimer(this);
connect(timer, SIGNAL(timeout()), this, SLOT(update()));
timer->start(1000);

再来看看ATimer的使用:

ATimer<> t;
t.bind([]{ std::cout << "Hello C++" << std::endl; });
t.start(1000);

从上面的例子可以看到,QTimer和ATimer的使用都非常方便,接下来看看ATimer的具体实现:

// ATimer.hpp
#ifndef _ATIMER_H
#define _ATIMER_H #include <vector>
#include <thread>
#include <atomic>
#include <functional>
#include <boost/timer.hpp>
#include <boost/asio.hpp> template<typename Duration = boost::posix_time::milliseconds>
class ATimer
{
public:
ATimer() : m_timer(m_ios, Duration(0)), m_isSingleShot(false) {}
~ATimer()
{
stop();
} void start(unsigned int duration)
{
if (m_ios.stopped())
{
return;
} m_isActive = true;
m_duration = duration;
m_timer.expires_at(m_timer.expires_at() + Duration(m_duration));
m_func = [this]
{
m_timer.async_wait([this](const boost::system::error_code&)
{
for (auto& func : m_funcVec)
{
func();
} if (!m_isSingleShot)
{
m_timer.expires_at(m_timer.expires_at() + Duration(m_duration));
m_func();
}
});
}; m_func();
m_thread = std::thread([this]{ m_ios.run(); });
} void stop()
{
m_ios.stop();
if (m_thread.joinable())
{
m_thread.join();
}
m_isActive = false;
} void bind(const std::function<void()>& func)
{
m_funcVec.emplace_back(func);
} void setSingleShot(bool isSingleShot)
{
m_isSingleShot = isSingleShot;
} bool isSingleShot() const
{
return m_isSingleShot;
} bool isActive() const
{
return m_isActive;
} private:
boost::asio::io_service m_ios;
boost::asio::deadline_timer m_timer;
std::function<void()> m_func = nullptr;
std::vector<std::function<void()>> m_funcVec;
std::thread m_thread;
unsigned int m_duration = 0;
std::atomic<bool> m_isSingleShot;
bool m_isActive = false;
}; #endif

下面是ATimer的具体使用例子:

// main.cpp
#include <iostream>
#include "ATimer.hpp" void test()
{
std::cout << "Timer thread id: " << std::this_thread::get_id() << std::endl;
} int main()
{
std::cout << "Main thread id: " << std::this_thread::get_id() << std::endl; ATimer<boost::posix_time::minutes> t0;
t0.setSingleShot(true);// 单次调用
t0.bind(test);
t0.start(1);// 一分钟之后调用 ATimer<> t;//默认使用毫秒定时器
t.bind(test);
t.bind([]{ std::cout << "Hello C++" << std::endl; });
t.start(1000);//每1000ms调用一次 std::cin.get();
t0.stop();
t.stop();
std::cout << "Tiemr stop" << std::endl; std::cin.get();
std::cout << "Process end" << std::endl; return 0;
}

该例子的github地址:https://github.com/chxuan/samples/tree/master/ATimer

使用boost的deadline_timer实现一个异步定时器的更多相关文章

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

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

  2. boost::asio::deadline_timer(理解)

    并发与并行: 并发和并行从宏观上来讲都是同时处理多路请求的概念.但并发和并行又有区别,并行是指两个或者多个事件在同一时刻发生:而并发是指两个或多个事件在同一时间间隔内发生. 1.Timer.1 - 使 ...

  3. c++11实现异步定时器

    c++11提供了丰富的时间和线程操作函数,比如 std::this_thread::sleep, std::chrono::seconds等.可以利用这些来很方便的实现一个定时器.     定时器要求 ...

  4. 深入理解Tornado——一个异步web服务器

    本人的第一次翻译,转载请注明出处:http://www.cnblogs.com/yiwenshengmei/archive/2011/06/08/understanding_tornado.html原 ...

  5. 分享一个异步任务在遇到IO异常时支持递归回调的辅助方法

    public void TryAsyncActionRecursively<TAsyncResult>( string asyncActionName, Func<Task<T ...

  6. 一个异步任务接收两个url下载两个图片

    有两个url,一个是下载用户头像的url,一个是下载用户上传图片的url,想要用一个异步任务同时下载这两个图片. 程序的下载任务是这么执行的,先接受url参数,然后调用 imgUrls = infoP ...

  7. Netty实现的一个异步Socket代码

    本人写的一个使用Netty实现的一个异步Socket代码 package test.core.nio; import com.google.common.util.concurrent.ThreadF ...

  8. 并发编程 —— 自己写一个异步回调 API

    1. 前言 在并发编程中,异步回调的效率不言而喻,在业务开发中,如果由阻塞的任务需要执行,必然要使用异步线程.并且,如果我们想在异步执行之后,根据他的结果执行一些动作. JDK 8 之前的 Futur ...

  9. 如何设计一个异步Web服务——任务调度

    接上一篇<如何设计一个异步Web服务——接口部分> Application已经将任务信息发到了Service服务器中,接下来,Service服务器改如何对自身的资源进行合理分配以满足App ...

随机推荐

  1. SFTPTool 和 FTPTooL.java

    两个工具类依赖的jar包: FTPTool.java public static void main(String[] args) throws Exception{ FTPTooL ftpTool ...

  2. ACM之递推递归

    Hdu 2569 突破蝙蝠的包围,yifenfei来到一处悬崖面前,悬崖彼岸就是前进的方向,好在现在的yifenfei已经学过御剑术,可御剑轻松飞过悬崖. 现在的问题是:悬崖中间飞着很多红,黄,蓝三种 ...

  3. 判断时间大小 yyyy-MM-dd 格式

    // yyyy-MM-dd function bigThanToday(someDate){ var date = new Date(); var dateStr = date.getFullYear ...

  4. 用来用去还是觉得SDCMS好用

    用来用去还是觉得SDCMS好用 现在可以算是精通了.呵呵,欢迎交流

  5. halcon的性能

    ·满足您各类机器视觉应用需求的完善的开发库 ·包含匹配,识别,定位及1D,2D,3D测量等多种高级算法 ·强大,易用的工具加速您的开发进程 ·与Linux/UNI及Windows(包括×64)兼容,避 ...

  6. 说下Fedora下把SpiderMonkey放入Eclipse内编译的过程

    首先要知道SpiderMonkey是个什么玩意 详细的可以看看这里(当然,如果你有google翻译的话看起来也一样费劲,你可以在语言那里选择中文.看完了再转回英文-因为中文有很多文档都没有的,比如:B ...

  7. js 浮点小数计算精度问题 parseFloat 精度问题

    在js中进行以元为单位进行金额计算时 使用parseFloat会产生精度问题 var price = 10.99; var quantity = 7; var needPay = parseFloat ...

  8. erlang: Programming Rules and Conventions。

    http://www.erlang.se/doc/programming_rules.shtml#HDR33 http://www.erlang.org/eeps/eep-0008.html

  9. Flex4 DataGrid ItemRenderer内嵌方式

    Flex4 DataGrid ItemRenderer像Flex3一直内嵌ItemRenderer会报空对象引用的错误,如: <s:GridColumn dataField="titl ...

  10. Javascript如何访问和处理系统文件

    一.功能实现核心:FileSystemObject 对象 要在javascript中实现文件操作功能,主要就是依靠FileSystemobject对象. 二.FileSystemObject编程 使用 ...