Use of the Boost.Chrono time library in C++

  • 2020-05-27 06:48:29
  • OfStack

preface

This thing everyone should understand somewhat, clock plays an important role in the process, sleep in system programming, with a timeout waiting for the timeout condition variables, with a timeout lock is used, but is often largely dependent on a particular system, even if you don't feel system, cross-platform, if we can use a stable interface, at the same time, if it can be convenient for time, time and other related operations and operations, will be better.

In the boost library, time-related libraries are Boost.DateTime and Boost.Chrono. The former focuses on time and localization, while the latter focuses on time, time and time calculation. C + + 11, of course, the standard has supported std: : chrono, compile but for compatibility with old systems now many C + + libraries and programs use boost. chrono as time class library (and the reason is that std: : chrono not included boost. chrono all functions, such as statistical CPU use time, custom output format, etc.), but is unfortunately even use boost: : chrono as a stopgap, It also requires boost-1.47, while older distributions now require an upgrade to the boost library. Considering that RHEL-6.x is still being deployed on a large scale, and that RedHat will be providing technical support for this product for up to 10 years, I don't know when it will be smooth to enjoy C++11...

The time types of Boost.Chrono are divided into duration and time_point, which are time and time. Many concepts and interfaces are defined and implemented around these two dimensions.

1. Clock

clock is an important concept in Boost.Chrono, and each of these clock contains one now() Is used to return the current time_point. Boost.Chrono contains the following types of clock:

(1) chrono::system_clock Represents the system time, such as the current time displayed on the computer. The feature is that the time can be manually set and updated by the user, so the clock can be synchronized with the external clock source. This clock has one more to_time_t() A member function that returns the number of seconds elapsed between the start of 1970.1.1 and a point in time. The data type is std::time_t . This kind of clock is usually used to convert into calendar time.

(2) chrono::steady_clock Is characterized by time is monotone increasing, after a moment the timing of the visit to get sure than the moment before get the timing of the night, even if we manually adjust system time forward will not change the clock steadily push forward the cumulative, it is also called monotonic time, the clock is uniform growth and can not be adjusted, it features for many do not allow time disordered system is an important of 10 points. chrono::steady_clock Timing is usually based on system startup time and is often used for time-consuming, waiting, and other tasks.

(3) chrono::high_resolution_clock Depending on the system implementation, usually a macro definition of the above two clocks, depending on which clock source is more accurate, so its output also depends on which clock is implemented.

(4) chrono::process_real_cpu_clock Represents the time CPU has been used since the process started, and this data can also be obtained using std::clock(). chrono::process_user_cpu_clock , boost::chrono::process_system_cpu_clock Represents the time spent in user state, kernel state, and all of these events can pass since the process started chrono::system_clock0 To get, he returns an tuple structure made up of all the time above.

(5) chrono::thread_clock Returns elapsed time based on thread statistics and does not distinguish between user and kernel time.

2. time_point

time_point represents a point in time, which is equivalent to the result of clock +duration at a certain time, while two time_point subtractions can also yield one duration. time_point is commonly described as :3 minutes later, 10:32:23 on January 1, 2038, 20ms after the timer is started...

Each of the above clock has an now() member function that returns chrono::time_point Type. This type is implemented using one template, so its actual type is highly dependent on the selected clock source.

Boost Chrono have one chrono::time_point_cast Conversion function that explicitly converts time_point from high to low granularity.


chrono::process_real_cpu_clock::time_point p = chrono::process_real_cpu_clock::now();
std::cout << chrono::time_point_cast<minutes>(p) << '\n';

3. duration

In terms of length, chrono::duration It is also a template type, with the first template parameter indicating the data type used for storage (int, long, double, etc.) and the second template parameter indicating ratio(such as 24, 60, 1000, etc.). For the convenience of users, Boost.Chrono provides six time types commonly used by duration, and they are all internally saved with an integer large enough to be used for their metering values count() The member function is:

chrono::nanoseconds , chrono::milliseconds , chrono::microseconds , chrono::seconds , chrono::minutes , chrono::hours , and overloads the calculation operators for each of these types: +, -, < And so on, convenient time calculation and comparison. The documentation says traditional Boost.DateTime Boost is implemented by inheritance.Chrono is more concise and efficient compared with Boost. Chrono and the former maintain a 1-like interface.


chrono::steady_clock::time_point start = chrono::steady_clock::now();
...
chrono::duration<double> sec = chrono::steady_clock::now() - start;
std::cout << "we took " << sec.count() << " seconds\n";
auto go = chrono::steady_clock::now() + chrono::nanoseconds(500); 
while (chrono::steady_clock::now() < go) 
... ;

The above six types of time_point represent dimensions that are not 1, and coarse-grained durations can certainly be represented in fine-grained types, otherwise precision may be lost, so they need to be used chrono::duration_cast() The function does the explicit conversion.

The above six types of time may not be great, but the point is that boost::chrono is now widely used in other libraries of boost. For example, let's look at a prototype with timeout for a condition variable:


template< typename Clock, typename Duration >
cv_status wait_until( std::unique_lock< mutex > & lk,
      std::chrono::time_point< Clock, Duration > const& abs_time);
      
template< typename Rep, typename Period >
cv_status wait_for( std::unique_lock< mutex > & lk,
     std::chrono::duration< Rep, Period > const& rel_time);

That means we can just go ahead and chrono::minutes{2} This duration object can be dropped into this function, and it is convenient to create any length of time with any precision, instead of focusing on the function interface as before: some people use seconds, some use milliseconds, and some use timeval.

Now, in both the boost library and the standard library, functions based on timeouts have the for suffix, while variables based on timeouts have the until suffix, such as this_thread::sleep_for() and this_thread::sleep_until() Similarly: wait, try_lock, unique_lock for conditional variables, mutex for mutual exclusion, unique_lock for operations.

4. Time output in a custom format

through time_fmt() You can format the output for the moment, including the header file.


time_fmt(boost::chrono::timezone::local, "%H:%M:%S");
time_fmt(boost::chrono::timezone::utc, "%H:%M:%S");

reference

Chapter 37. Boost.Chrono

Chapter 8. Boost.Chrono 2.0.5

conclusion


Related articles: