时间在C++中的具体表示方式。
1、时钟类
就C++标准库而言,时钟(clock)是时间信息的来源。具体来说,每种时钟都是一个类,提供4项关键信息:
- 当前时刻;
- 时间值的类型(从该时钟取得的时间以它为表示形式);
- 该时钟的计时单元的长度(tick period);
- 计时速率是否恒定,即能否将该时钟视为恒稳时钟(steady clock)。
若要获取某时钟类的当前时刻,调用其静态成员函数now() 即可。每个时钟类都具有名为 time_point 的成员类型,它是该时钟类自有的时间点类。
//返回系统时钟的当前时刻,返回值的类型就是system_clock::time_point
std::chrono::system_clock::now();
cout<<std::chrono::system_clock::to_time_t(std::chrono::system_clock::now())<<endl;//等于 time(NULL);
时钟类的计时单元属于名为period的成员类型,它表示为秒的分数形式。若时钟每秒计数25次,它的计时单元即为std::ratio<1,25>;(1/25s)。
若时钟的计时速率恒定(无论速率是否与计时单元相符)且无法调整,则称之为恒稳时钟。时钟类具有静态数据成员is_steady,该值在恒稳时钟内为true,否则为false。
- std::chrono::system_clock类不是恒稳时钟,因为它可调整。
- C++标准库提供了恒稳时钟类std::chrono::steady_clock。
- 高精度时钟类std::chrono::high_resolution_clock
2、时长类
std::chrono::duration<>是标准库中最简单的时间部件。它是类模板,具有两个模板参数,前者指明采用何种类型表示计时单元的数量(如int、long或double),后者是一个分数,设定该时长类的每一个计时单元代表多少秒。
例,采用short值计数的分钟时长类是std::chrono::duration<short,std::ratio<60,1>>。
标准库在std::chrono名字空间中,给出了一组预设的时长类的typedef声明:nanoseconds、microseconds、milliseconds、seconds、minutes和hours,分别对应纳秒、微秒、毫秒、秒、分钟、小时
C++14引入了名字空间std::chrono_literals,其中预定义了一些字面量后缀运算符。
using namespace std::chrono_literals;
auto one_day=24h;
auto half_an_hour=30min;
auto max_time_between_messages=30ms;
//15ns和std::chrono::nanoseconds(15)是两个相等的值
显式转换通过std::chrono::duration_cast<>完成。
std::chrono::miliseconds ms(54802);
std::chrono::seconds s = std::chrono::duration_cast<std::chrono::seconds>(ms);//结果被截断,而非四舍五入,故此,时长变量s的值是54
时长类支持算术运算,将时长乘或除以一个数值(这个数值与该时长类的计数类型相符,即其第一个模板参数),或对两个时长进行加减,就能得出一个新时长。所以,5*seconds(1)等于seconds(5),还等于minutes(1) −seconds(55)。
计时单元的数量可通过成员函数count()获取,因而std::chrono::milliseconds(1234).count()得到1234。
3、时间点类
时间点由类模板std::chrono::time_point<>的实例表示,它的第一个模板参数指明所参考的时钟,第二个模板参数指明计时单元[19](std::chrono::duration<>的特化)。
可以在给定的时间点上调用time_since_epoch(),这个成员函数返回一个时长对象,表示从时钟纪元到该时间点的时间长度。
可以用std::chrono::time_pointstd::chrono::system_clock,std::chrono::minutes指定一个时间点,它持有某个时刻,以系统时钟为参考,计时单元则为分钟。
我们可将时间点加减时长(即令std::chrono::time_point<>的实例加减std::chrono::duration<>实例),从而得出新的时间点。据此,std::chrono::high_resolution_clock:: now() + std::chrono::nanoseconds(500)会给出500纳秒以后的未来时刻。
auto start=std::chrono::high_resolution_clock::now();
//usleep(2*1000*1000+820*1000);
sleep(2);
auto stop=std::chrono::high_resolution_clock::now();
cout<<std::chrono::duration_cast<std::chrono::seconds>(stop-start).count()<<" seconds | "<<(stop-start).count()<<" ns"<<endl;
//输出2 seconds | 2000080569 ns
接受超时时限的函数
有两种超时机制可供选用:
- 一是迟延超时(duration-based timeout),线程根据指定的时长而继续等待(如30毫秒);
- 二是绝对超时(absolute
timeout),在某特定时间点来临之前,线程一直等待。
处理迟延超时的函数变体以“_for”为后缀,而处理绝对超时的函数变体以“_until”为后缀。
例如,std::this_thread::sleep_for()和std::this_thread::sleep_until()。它们的功能就像简单的闹钟:线程或采用sleep_for()按指定的时长休眠(接收std::duration<>实例),或采用sleep_until()休眠直到指定时刻为止(接收std::duration<>)。