九、 通用工具 ----clock和Timer

来源:互联网 发布:宜嘉情感分析 知乎 编辑:程序博客网 时间:2024/06/06 13:11

7 clock和Timer

  1. c++11提供一个精度中立的程序库(chrono程序库),定义与<chrono>
  2. c++标准库也提供基本的c和posix接口,处理日历时间;

1 chrono程序库简介

目的:

  1. 希望处理“timer和clock在不同的系统中可能不同”的事实;
  2. 强化时间精度
  3. 提供精度中立的概念,将duration(时间段)和timepoint(时间点)从特定的clock区分开来;

chrono程序组成:

  1. duration(时间段): 某时间单位上的一个明确的tick(片可数)
  2. timepoint(时间点):一个duration和一个epoch(起始点)的组合;
  3. timepoint以某个clock为参数;Clock是一个对象,定义了timepoint的起点;
    timer时间点

2 duration(时间段)

duration是一个数值(表现tick个数)和一个分数(表现时间单位,以秒计时)的组合;其中分数由ratio描述;
例如:

//默认为秒为单位std::chrono::duration<int>   twentySeconds(20);//一分钟为单位(60/1)std::chrono::duration<double,std::ratio<60>> halfAMinute(0.5); //0.5 * 60//以一毫秒为单位(1/1000)std::chrono::duration<long,std::ratio<1,1000>>  oneMillisecond(1);// 1毫秒

2.1 duration预定义

c++标准库提供的定义:

类型 定义 std::chrono::nanoseconds duration</*至少 64 位的有符号整数类型*/, std::nano> std::chrono::microseconds duration</*至少 55 位的有符号整数类型*/, std::micro> std::chrono::milliseconds duration</*至少 45 位的有符号整数类型*/, std::milli> std::chrono::seconds duration</*至少 35 位的有符号整数类型*/> std::chrono::minutes duration</*至少 29 位的有符号整数类型*/, std::ratio<60>> std::chrono::hours duration</*至少 23 位的有符号整数类型*/, std::ratio<3600>>

有了这些定义:

std:: chrono:: seconds twentyseconds(20);  //20秒

2.2 duration的算术运算

duration的算术运算
说明:

  1. 可以计算两个duration的和,差积商;
  2. 可以加减两个tick,或者加减其他duration;
  3. 可以比较两个duration的大小;

主要的地方:

  1. 运算的两个duration的单位类型可以不同;
  2. 标准库的common_type<>为duration提供了一个重载版本,因此运算的得到的duration其单位是两个操作的单位的最大公约数;

例如:

chrono::seconds d1(42);  //42 秒chrono::milliseconds d2(10);  //10毫秒//d1- d2的结果为://拥有“41990个毫秒单位”的一个duration
  1. 可以将duration转换为不同的单位,只要彼此之间存在隐式转换;因此,可以将小时转换为秒,反向不行;

2.3 duration的其他操作

duration的其他操作
说明:

  1. duration可以进行隐式转换到一个“比较精准的单位类型”:无精度损失
  2. 隐式转换但是不能转换至“比较粗糙的单位类型”:有精度损失

例如:
1. 将一个42010毫秒转换到秒:42秒,这个duration中的10毫秒丢失了,这是不行的;
2. 但是可以使用duration_cast<>进行强制转换

std::chrono::seconds sec(55);std::chrono::minutes m1 = sec; //errorstd::chrono::minnutes m2 = std::chrono::duration_cast<std::chrono:::minutes>(sec);  //ok

因此,利用强制转换,可以进行将duration切割成不同的单元;
例如:

//---------省略-------------using namespace std;using namespace std::chrono;//--------------省略----------milliseconds ms(7255042);hours hh = duration_cast<hours>(ms);minutes mm = duration_cast<minutes>(ms%hours(1));seconds ss = duration_cast<seconds>(ms%minutes(1));milliseconds msec = duration_cast<milliseconds>(ms%seconds(1));cout << "   " << setfill('0') << setw(2) << hh.count() << "::"    << setw(2) << mm.count() << "::" << setw(2) << ss.count() << "::"    << setw(2) << msec.count() << endl;//结果为:02::00::55::42

说明: 部分vs2013支持部分c++11,不能通过编译,因此需要更新的编译器;

3 clock和Timepoint

timepoint 和clock:

  • clock: 定义了一个epoch(起始点)和一个tick周期;
  • Timepoint:表现某个特定的时间点,关联到某个clock的某个正值或者负值的duration;

3.1 clock

clock操作

c++标准库提供了三个clock接口:

  • system_clock: 所表现的timepoint关联到系统的即时时钟,这个接口提供to_time_t()from_time_t()两个函数,允许将timepoint和“c类型的系统时间类型”time_t之间转换,意味着可以转换到日历时间;

  • steady_clock: 保证绝对不会被调整;当实际时间流逝的时候,timepoint值不会减少,用来计算时间间隔;

  • high_resolution_clock: 表现的是当前系统中带有最短tick的clock;它可能是system_clock或stable_clock的同义词。

3.2 Timepoint

3.2.1 time_point的定义

定义为:

template <class Clock, class Duration = typename Clock::duration>  class time_point;

四个特定的timepoint:
- Epoch: 由任何clock的time_point的默认构造函数产出;
- Current time: 由任何的clock的static成员函数now()产出;
- Minimum timepoint: 由任何clock的time_point的static成员函数min()产生;
- Maximum timepoint: 由任何clock的time_point的static成员函数max()产出;
例子:

#include <chrono>#include <iostream>#include <iomanip>using namespace std;using namespace std::chrono;string  asString (const chrono::system_clock::time_point & tp){    time_t t = chrono::system_clock::to_time_t(tp);    string ts = ctime(&t);    return ts;}int main(){chrono::system_clock::time_point tp;cout<<"epoch: "<<asString(tp) ;tp = chrono::system_clock::now();cout<<"now: "<<asString(tp);//tp = chrono::system_clock::time_point::min();//cout<<"min: "<<asString(tp);//tp = chrono::system_clock::time_point::max();//cout<<"max: "<<asString(tp);}

min()和max()出错,不知道哪里有问题!
输出为:

epoch: Thu Jan 01 08:00:00 1970now: Thu Aug 31 11:20:44 2017

说明:

  1. 只有system_clock才有接口从time_point转到time_t类型;

3.2.2 time_point的 操作

timepont的操作

4 C和posix提供的Date/Time函数

  1. C语言以供的接口在<time.h>,现在位于c++<ctime>中;

4.1 ctime中的预定义

ctime
说明:

  1. time_t通常只是“始于unix epoch(1970年1月1日)的秒数;”

4.1.2 类型成员

  • clock_t
  • size_t
  • time_t
  • struct tm

结构体 tm的成员:

int tm_sec   //秒  在minute后 – [0, 60][note 1] int tm_min   //分钟,在1小时后 - [0,59]int tm_hour   //小时,自午夜开始 - [0,23]int tm_mday  //月的一天 - [1,31]int tm_mon   //1月,0开始 - [0,11]int tm_year //年,自1900年以来int tm_wday  //自上周日以来- [0,6]int tm_yday  //天,自1月1日 - [0,365]int tm_isdst //夏令时间标志。大于0表示夏令时,如果夏令时没有效果,则为零,如果信息不可用,小于零。(公开成员对象)

5 以计时器停滞线程

duration和timepoint可以用来停滞线程或者程序;
例如:

  1. sleep_for()和sleep_until():由this_thread提供的来停滞线程;
  2. try_lock_for()和try_lock_until(),用来等待一个mutex时指定最大时间段;
  3. wait_for()和wait_until(),用来等待某条件成立或等待一个future时指定最大时间段;

说明:

  1. 所有以..for()结束的停滞函数需要一个duration
  2. 所有以..until()结束的停滞函数需要一个timepoint
  3. 这些timer都不保证绝对精准

例子:

this_thread::sleep_for(chrono::seconds(10));  //停滞当前线程10this_thread::sleep_until(chrono:system_clock::now() + chrono::seconds(10) ) ; //停滞当前线程直到system_clock来到比当前多10秒的timepoint