boost库下的deadline_timer和steady_timer 区别
1:steady_timer的expires_from_now函数参数必须使用std::chrono
2:deadline_timer的expires_from_now函数参数必须使用boost::posix_time
声明以下处之别人的整理中
3:boost::asio::deadline_timer使用的计量时间是系统时间,因此修改系统时间会影响deadline_timer的行为。例如,调用了expires_from_now设置1分钟超时后,立刻把系统时间改成一天前,那么要过一天时间才会超时。这个特性可能会影响程序功能的正常使用,因此我们通常想要的是一个不会受系统时间影响的定时器。
事实上,boost::asio::steady_timer就是一个这样的定时器,它基于std::chrono::steady_clock实现。std::chrono::steady_clock是一个稳定的时钟,不随系统时间变化而变化。既然如此,直接用steady_timer代替deadline_timer不就可以了吗?理论上来说是可以的,但实际上,在Visual C++ 2013环境下,这是行不通的,因为Visual C++ 2013标准库中的std::chronno::steady_clock并不符合标准,它仍然会受系统时间影响!
有三种方法可以解决这个问题。第一是升级到Visual C++ 2015,这个版本的std::chronno::steady_clock总算符合标准了;第二是修改boost的编译选项,定义BOOST_ASIO_DISABLE_STD_CHRONO宏,这样可以禁止boost使用std::chrono,转而使用boost::chrono;第三是本文要介绍的方法,即定制deadline_timer,让它变成稳定的定时器。
deadline_timer实际上是basic_deadline_timer的特化版本,它的定义如下:
typedef basic_deadline_timer<boost::posix_time::ptime> deadline_timer;
basic_deadline_timer是一个模板类,它的定义如下:
template<
typename Time,
typename TimeTraits = boost::asio::time_traits<Time>,
typename TimerService = deadline_timer_service<Time, TimeTraits>>
class basic_deadline_timer : public basic_io_object< TimerService >
从以上定义的模板参数可以看出,basic_deadline_timer提供了灵活的可定制性。这里我们关注的重点是前面两个模板参数,其中第一个参数Time指定时间值的类型,第二个参数TimeTraits指定时间值的特性类,特性类用来对时间值进行各种操作。TimeTraits使用boost::asio::time_traits作为默认值,而boost::asio::time_traits只有一个针对boost::posix_time::ptime(即deadline_timer使用的时间值类型)的特化版本,从这个特化版本的定义可以看到TimeTraits需要提供哪些接口,如下所示:
/// Time traits specialised for posix_time.
template <>
struct time_traits<boost::posix_time::ptime>
{
/// The time type.
typedef boost::posix_time::ptime time_type;
/// The duration type.
typedef boost::posix_time::time_duration duration_type;
/// Get the current time.
static time_type now()
{
#if defined(BOOST_DATE_TIME_HAS_HIGH_PRECISION_CLOCK)
return boost::posix_time::microsec_clock::universal_time();
#else // defined(BOOST_DATE_TIME_HAS_HIGH_PRECISION_CLOCK)
return boost::posix_time::second_clock::universal_time();
#endif // defined(BOOST_DATE_TIME_HAS_HIGH_PRECISION_CLOCK)
}
/// Add a duration to a time.
static time_type add(const time_type& t, const duration_type& d)
{
return t + d;
}
/// Subtract one time from another.
static duration_type subtract(const time_type& t1, const time_type& t2)
{
return t1 - t2;
}
/// Test whether one time is less than another.
static bool less_than(const time_type& t1, const time_type& t2)
{
return t1 < t2;
}
/// Convert to POSIX duration type.
static boost::posix_time::time_duration to_posix_duration(
const duration_type& d)
{
return d;
}
};
可以看到,TimeTraits需要提供time_type和duration_type两种类型来分别表示一个时间点和一段时间;需要提供now方法来获取当前时间;需要提供add、subtract和less_than方法来计算和比较时间;最后还需要to_posix_duration方法把duration_type类型转换成boost::posix_time::time_duration类型。
显然,对于定制的basic_deadline_timer,时间值类型Time可以是任意类型,并且它的含义并没有硬性规定,例如,它可以是以毫秒或纳秒为单位的时间,也可以是CPU时钟的周期数,只要提供了正确的TimeTraits特性类把这个定制的时间值转换成boost认识的时间值即可。
接下来要选择一种与系统时间无关的时间值类型来定制basic_deadline_timer。在Windows平台下,很容易想到可以使用QueryPerformanceCounter和QueryPerformanceFrequency,这两个API提供了高精度的时间度量,与系统时间无关。QueryPerformanceCounter用来查询当前CPU时钟的周期数,是64位整数,这个是理想的时间值类型。要把CPU时钟周期数转换成具体的时间还需要调用QueryPerformanceFrequency查询CPU时钟的频率,即1秒内的CPU时钟周期数,然后通过简单的计算即可得到。
下面的是使用QueryPerformanceCounter和QueryPerformanceFrequency定制的TimeTraits:
class TimeTraits {
public:
typedef std::int64_t time_type;
class duration_type {
public:
duration_type() : value(0) { }
duration_type(std::int64_t value) : value(value) { }
std::int64_t value;
};
public:
static void Initialize() {
LARGE_INTEGER frequence_large_integer = { 0 };
QueryPerformanceFrequency(&frequence_large_integer);
frequence = frequence_large_integer.QuadPart;
}
static duration_type GetMinutes(std::int64_t minutes) {
return duration_type(minutes * 60 * frequence);
}
static duration_type GetSeconds(std::int64_t seconds) {
return duration_type(seconds * frequence);
}
static duration_type GetMilliseconds(std::int64_t milliseconds) {
return duration_type(milliseconds * (frequence / 1000));
}
static time_type now() {
LARGE_INTEGER counter = { 0 };
QueryPerformanceCounter(&counter);
return counter.QuadPart;
}
static time_type add(time_type time, duration_type duration) {
return time + duration.value;
}
static duration_type subtract(time_type time1, time_type time2) {
return duration_type(time1 - time2);
}
static bool less_than(time_type time1, time_type time2) {
return time1 < time2;
}
static boost::posix_time::time_duration to_posix_duration(duration_type duration) {
std::int64_t microseconds = (duration.value * 1000 * 1000) / frequence;
return boost::posix_time::microseconds(microseconds);
}
private:
TimeTraits();
private:
static std::int64_t frequence;
};
CPU时钟的频率是固定的,只需要调用QueryPerformanceFrequency查询一次即可,因此这里增加了Initialize方法来初始化CPU时钟频率,要在程序启动后的某个时机来调用该方法进行初始化。要注意的是duration_type不能跟time_type相同,这是TimeTraits的硬性规定,boost内部的代码依赖了这个规定,违反它会导致编译失败。所以要针对duration_type额外定义一个看似冗余的类型。
另一个值得注意的地方是,上面的定义增加了GetMinutes、GetSeconds和GetMilliseconds方法,这几个方法用来将具体的时间转换成我们定制的时间值,即CPU时钟周期数。这是因为在调用定时器的expires_from_now等方法设置超时值的时候,必须使用TimeTraits的duration_type,提供这几个方法可以方便使用。
最后,将这个定制的TimeTraits作为basic_deadline_timer的模板参数即可:
typedef boost::asio::basic_deadline_timer<std::int64_t, TimeTraits> Timer
使用方法基本上与dealine_timer一样,如下所示:
//在某个时机初始化TimeTraits
TimeTraits::Initialize();
//在某个地方定义io_service
boost::asio::io_service io_service;
//使用定制的Timer
Timer timer(io_service);
timer.expires_from_now(TimeTraits::GetSecnods(10));
timer.wait();
|
boost库下的deadline_timer和steady_timer 区别相关推荐
- Boost库之asio io_service以及run、run_one、poll、poll_one区别
Boost库之asio io_service以及run.run_one.poll.poll_one区别 原文:http://blog.csdn.net/byxdaz/article/details/7 ...
- Windows下Boost库的安装与使用
目录 1.基本介绍 2.下载安装 3.配置boost环境(VS2010) 4.测试 1.基本介绍 Boost库是为C++语言标准库提供扩展的一些C++程序库的总称,由Boost社区组织开发.维护.其目 ...
- Mysql依赖库Boost的源码安装,linux下boost库的安装
boost'准标准库'安装过程. 安装的是boost_1_60_0. (1)首先去下载最新的boost代码包,网址www.boost.org. (2)进入到自己的目录,解压: bzip2 -d boo ...
- Linux下安装和使用boost库
Linux下安装和使用boost库 2016-08-26 20:29:06 zhaomax 阅读数 349更多 分类专栏: C++ 用boost库中的serialization库.Boost库分为两个 ...
- Linux下boost库的编译、安装详解
1.下载源文件 去官网下载:http://www.boost.org/ 这里下载最新版本 wget https://dl.bintray.com/boostorg/release/1.64.0/sou ...
- VS2008下直接安装使用Boost库1.46.1版本号
Boost库是一个可移植.提供源码的C++库,作为标准库的后备,是C++标准化进程的发动机之中的一个. Boost库由C++标准委员会库工作组成员发起,当中有些内容有望成为下一代C++标准库内容.在C ...
- VS2010下安装boost库
1.去www.boost.org下载最新的boost,我下载了boost_1_46_1.7z 2.(我放在D:/cpp目录下)解压到当前文件夹 3.打开VS2010->VS TOOLS-> ...
- linux boost 卸载,Ubuntu下boost库的编译安装步骤及卸载方法详解
最近由于编译一个程序用到了C++的boost库,所以便安装了这个库.但是,其中遇到了一些小问题.所以记录下来,以供别人参考. 首先说一下我的环境:Ubuntu 12.04 32bit, gcc 4. ...
- Windows下编译和安装Boost库
因为boost都是使用模板的技术,所以所有代码都是写在一个.hpp头文件中.这样boost中的大部分内容是不需要编译生成相应的链接库,只需要设置下面的包含目录(或者设置一下环境变量),在源文件中包含相 ...
最新文章
- mysql等待事件类型_Oracle中常见的33个等待事件小结
- centos7配网卡_centos7配置网卡
- Docker持续集成与容器管理--系列教程
- java与php链条遇到的坑,记一次Java加密加签算法到php的坑
- 图片压缩的另一种实现(3)
- 计算机丢失faultrep.dll,faultrep.dll
- linux 磁盘清理脚本,磁盘清理脚本
- 程序设计实践(评注版) 评注者序
- angular表单验证
- 将Excel(.xlsx)中的数据导入到数据库中
- php dom怎么创建节点,前端必须掌握的DOM节点操作方法!
- 数学建模线性规划实例及详细解答(MATLAB代码)
- jqGrid分页点击事件,点击分页的时候滚动条回到顶端
- 计算机画图照片大小,如何压缩图片大小,用电脑系统自带画图工具即可
- jquery 移动端 ui 组件库 移动端前端UI库—Frozen UI、SUI Mobile、light7、WeUI、jqweui
- windows使用密钥登录linux服务器
- 中医大2020年7月网考计算机应用基础,2020年7月网络教育统考《计算机应用基础》Internet应用模拟题试卷2...
- 高数 | 为什么f(x)从a到b的积分等于从b到a的积分的相反数?
- 项目实战:PB/ORACLE:C/S架构 学生成绩教务管理系统
- 2020-05-09 工作中英语单词积累
热门文章
- Perl的浅拷贝和深度拷贝
- 网络框架 Retrofit(三)
- [3/21]Windows Server 2008时钟方面的改进展示
- 【无私分享:从入门到精通ASP.NET MVC】从0开始,一起搭框架、做项目(5.5) 登录功能的实现,完善登录功能...
- C#学习笔记(十三):I/O操作
- Spring的基本使用
- Maven高级之插件开发
- MySQL在DOS指令里面的使用以及增删改查的使用
- 统计指定目录下的视频时长
- postgresql 插入 时间戳_数据也玩躲猫猫?PostgreSQL中别人提交的数据,我为什么看不到?...