- 跨平台、可移植一直是很多C++程序员追求的目标。但由于C++是一种中级语言,很多时候都要和操作系统打交道,因而功能代码常常和平台结合很紧密,难以做到真正的跨平台,再向其他平台移植代码的时候修改操作系统相关的代码通常是必不可少的工作
- boost库提供了数个操作系统相关的库,部分的屏蔽了操作系统的底层细节,能够提高程序的可移植性。比如说system库,它封装了操作系统底层的错误代码,为上层提供了一个可移植的统一的处理接口; chrono、cpu_time库基于操作系统的API提供高精度的时间功能
chrono完全实现了C++标准里定义的时间处理库,并且额外增加了一些功能。
- chrono库里的很多时间概念于date_time库类似,但它更侧重于表达”计算机世界“里的时间,所以是一个很重要的基础库,被cpu_time、thread等库使用
- chrono库需要编译,并且依赖system库,在jamfile里指定lib的语句是:
lib boost_chrone: boost_system:
boost_chrono; - chrono库提供宏
BOOST_CHRONO_HEADER_ONLY
,可以把chrone库完全头文件化,不需要编译或者链接(但还需要链接system库)- chrono库位于名字空间
boost::chrono
,需要包含头文件,为了使用扩展功能( chrono库另有一个头文件
,包含了很多扩展功能),需要定义宏
BOOST_CHRONO_EXTENSIONS
, 即:
//#define BOOST_ERROR_CODE_HEADER_ONLY // 无需编译即可使用system库
#define BOOST_CHRONO_HEADER_ONLY // 无需编译即可使用chrono库
#define BOOST_CHRONO_EXTENSIONS // 使用扩展功能
#include // 头文件
using namespace boost;
using namespace boost::chrono;
chrono库定义了时间长度的表示duration(注:chrono不关心历史日期,没有date_time库里的date的概念),在概念上于date_time库的time_duration相同,都表示一定长度的时间,但duration侧重于编译期的时间单位表示,更接近ratio,所以与time_duration的接口非常不同。
template <class Rep, class Period>
class duration
{
public:
typedef Rep rep; //内部类型定义
typedef Period period;
private:
rep rep_; //时间单位的计数
public:
BOOST_CONSTEXPR duration(); // 构造函数
explicit duration(const Rep2& r);
//~duration() {} //= default;
// BOOST_CONSTEXPR duration(const duration& rhs) : rep_(rhs.rep_) {} // = default;
duration& operator=(const duration& rhs);
// conversions
duration(const duration<Rep2, Period2>& d );
BOOST_CONSTEXPR rep count() const ;
// arithmetic
BOOST_CONSTEXPR duration operator+() const;
BOOST_CONSTEXPR duration operator-() const ;
duration& operator++() {++rep_; return *this;}
duration operator++(int) {return duration(rep_++);}
duration& operator--() {--rep_; return *this;}
duration operator--(int) {return duration(rep_--);}
duration& operator+=(const duration& d);
duration& operator-=(const duration& d);
duration& operator*=(const rep& rhs);
duration& operator/=(const rep& rhs) ;
duration& operator%=(const rep& rhs);
duration& operator%=(const duration& rhs);
static BOOST_CONSTEXPR duration zero();
static BOOST_CHRONO_LIB_CONSTEXPR duration min ();
static BOOST_CHRONO_LIB_CONSTEXPR duration max ();
};
typedef duration<boost::int_least64_t, nano> nanoseconds; // at least 64 bits needed
typedef duration<boost::int_least64_t, micro> microseconds; // at least 55 bits needed
typedef duration<boost::int_least64_t, milli> milliseconds; // at least 45 bits needed
typedef duration<boost::int_least64_t> seconds; // at least 35 bits needed
typedef duration<boost::int_least32_t, ratio< 60> > minutes; // at least 29 bits needed
typedef duration<boost::int_least32_t, ratio<3600> > hours; // at least 23 bits needed
typedef duration<long, ratio<30>> half_min; //半分钟
typedef duration<int, ratio<60*15>> quater; //一刻钟
typedef duration<double, ratio<3600*24>> day; //一天
//typedef duration my_hour; //编译错误,不能直接使用整数
//typedef duration> my_ms; //编译错误,不能用负数
duration就像是一个捆绑了算术类型的ratio,或者是一个带有时间单位的数字类型
seconds s(10); // 10s,相当于10 * ratio<1>
minutes m(5); // 5min, 相当于 5 * ratio<60>
hours h(1); // 1h, 相当于 1 * ratio<3600>
milliseconds ms(100); // 100ms, 相当于 100 * ratio<1, 1000>
assert(s.count() == 10); //使用成员函数
assert(ms.count() == 100);
s *= 3;
s += seconds(30);
s = s - seconds(20);
assert(s < seconds(50));
std::cout << s << std::endl;
seconds s(10);
minutes m(5);
s += m; //混合不同的时间单位运算
cout << s << endl; //输出”310 seconds“
//m+= s; //编译失败,整数类型不能表示小数概念
seconds s(10); //10s
typedef duration<double, ratio<60>> my_min; //定义新的时间单位
my_min m(5); // 5分钟
m += s; //混合不同的时间单位运算
cout << m << endl; //输出”5.1667 minutes“
using namespace std;
seconds s(30); // 30s
auto m = duration_cast<minutes>(s);
cout << m << endl; //"0 minutes"
seconds s2(301);
cout << duration_cast<minutes>(s2) << endl; // "5 minutes"
using namespace std;
seconds s(3600 + 50); //1h + 50s
cout << floor<minutes>(s) << endl;
cout << ceil<minutes>(s) << endl;
cout << round<minutes>(s) << endl;
cout << round<hours>(s) << endl;
时钟Clock是chrono里的另一个概念,它确定了一个时间的起点(since)和时间单位(duration)。使用时钟我们就可以处理计算机世界里的时间。
chrono库实现了C++标准里定义的三个时钟:
时钟 | 说明 |
---|---|
system_clock | 计算机实际时间(system_clock的计时起点是1970-1-1) |
steady_clock | 稳定的时钟,不会因为系统时间调整而变化 |
high_resolution_clock | 高分辨率的时钟,但通常是前两者的typedef |
时钟 | 说明 |
---|---|
process_real_cpu_clock | 进程执行的实际时间 |
process_user_cpu_clock | 用户CPU时间 |
process_system_cup_clock | 系统CPU时间 |
thread_clock | 线程执行的实际时间 |
各时钟的接口基本相同,比如:
class BOOST_CHRONO_DECL system_clock
{
public:
typedef BOOST_SYSTEM_CLOCK_DURATION duration; //时间单位
typedef duration::rep rep; //计数单位
typedef duration::period period; //ratio
typedef chrono::time_point<system_clock> time_point; //时间点
BOOST_STATIC_CONSTEXPR bool is_steady = false; //是否是稳定时钟
static BOOST_CHRONO_INLINE time_point now() BOOST_NOEXCEPT; //获取当前时间
#if !defined BOOST_CHRONO_DONT_PROVIDE_HYBRID_ERROR_HANDLING
static BOOST_CHRONO_INLINE time_point now(system::error_code & ec);
#endif
//转换到C里面的time_t结构
static BOOST_CHRONO_INLINE std::time_t to_time_t(const time_point& t) BOOST_NOEXCEPT;
static BOOST_CHRONO_INLINE time_point from_time_t(std::time_t t) BOOST_NOEXCEPT;
};
使用辅助类clock_string的两个静态成员函数name()、since()可以获取时钟的描述信息:
template<class CharT>
struct clock_string<system_clock, CharT>
{
static std::basic_string<CharT> name(); //时钟的名字
static std::basic_string<CharT> since(); //时钟的起点
};
template<typename T>
using clock_desc = clock_string<T, char>;
void case3()
{
using namespace std;
cout << clock_desc<system_clock>::name() << endl;
cout << clock_desc<system_clock>::since() << endl;
cout << clock_desc<steady_clock>::name() << endl;
cout << clock_desc<steady_clock>::since() << endl;
cout << clock_desc<process_real_cpu_clock>::name() << endl;
cout << clock_desc<process_real_cpu_clock>::since() << endl;
}
int main()
{
case3();
}
时间点time_point与时钟紧密关联,它必须由一个时钟产生,标记了自时钟起点以来所经过的时间。
template <class Clock, class Duration>
class time_point
{
public:
typedef Clock clock; //内部类型定义
typedef Duration duration;
typedef typename duration::rep rep;
typedef typename duration::period period;
typedef Duration difference_type;
private:
duration d_; //时间长度
public:
BOOST_CONSTEXPR time_point() ; //构造函数
BOOST_CONSTEXPR explicit time_point(const duration& d);
BOOST_CONSTEXPR duration time_since_epoch() const; //返回时间长度
#ifdef BOOST_CHRONO_EXTENSIONS
BOOST_CONSTEXPR time_point operator+() const {return *this;}
BOOST_CONSTEXPR time_point operator-() const {return time_point(-d_);}
time_point& operator++() {++d_; return *this;}
time_point operator++(int) {return time_point(d_++);}
time_point& operator--() {--d_; return *this;}
time_point operator--(int) {return time_point(d_--);}
time_point& operator+=(const rep& r) {d_ += duration(r); return *this;}
time_point& operator-=(const rep& r) {d_ -= duration(r); return *this;}
#endif
time_point& operator+=(const duration& d) {d_ += d; return *this;}
time_point& operator-=(const duration& d) {d_ -= d; return *this;}
// special values
static BOOST_CHRONO_LIB_CONSTEXPR time_point min() //最前可以表示的时间点
static BOOST_CHRONO_LIB_CONSTEXPR time_point max(); //最后可以表示的时间点
};
使用方法:
void case3()
{
typedef duration<double, ratio<3600*24>> day;
using namespace std;
auto tp1 = system_clock::now();
cout << tp1 << endl;
auto d = tp1.time_since_epoch();
cout << duration_cast<hours>(d) << endl;
cout << duration_cast<day>(d) << endl;
auto tp2 = tp1 +minutes(1);
cout << tp2 << endl;
}
using namespace std;
typedef duration<double, ratio<3600*24>> day;
auto tp = steady_clock::now();
cout << tp << endl;
auto d = tp.time_since_epoch();
cout << round<minutes>(d) << endl;
cout << round<hours>(d) << endl;
C++14新增了h/s/m/ms等字面值,用来便捷的声明duration变量。在C++11中我们同样可以定义自己的字面量:
hours operator"" _h(unsigned long long n)
{
return hours(n);
}
seconds operator"" _s(unsigned long long n)
{
return seconds(n);
}
milliseconds operator"" _ms(unsigned long long n)
{
return milliseconds(n);
}
void case3()
{
using namespace std;
auto h = 5_h;
auto s = 45_s;
auto ms = 200_ms;
cout << h << "; "<< s << "; "<< ms << endl;
}
auto tp = system_clock::now();
auto t = system_clock::to_time_t(tp);
cout << std::ctime(&t) << endl;
class steady_timer final {
private:
typedef boost::chrono::steady_clock clock_type; //定义时钟类型
typedef clock_type ::time_point time_point_type; //定义时间点类型
typedef boost::chrono::milliseconds duration_type; //使用微秒精度
time_point_type m_start = clock_type::now(); //构造时记录时间点
public:
steady_timer() = default;
~steady_timer() = default;
public:
void restart(){ //重启计时器
m_start = clock_type ::now();
}
duration_type elapsed() const {
return round<duration_type>(clock_type::now() - m_start); //将流逝时间转换为微妙
}
};
int main()
{
using namespace std;
steady_timer t;
sleep(1);
cout << t.elapsed() << endl;
}