| <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> |
| <html><head> |
| <meta http-equiv="content-type" content="text/html; charset=ISO-8859-1"> |
| |
| |
| <title>time2_demo</title> |
| </head><body> |
| |
| <pre><font color="#c80000">/* |
| Copyright (c) 2008 Howard Hinnant |
| |
| Distributed under the Boost Software License, Version 1.0. (See accompanying |
| file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) |
| |
| |
| A prototype of a proposal for a time/duration/clock library for the C++ standard. |
| It is intended that this be a solid foundation upon which higher level libraries |
| can be based. Examples of such libraries include a date/time library and a |
| physical quantities library. |
| |
| Two general purpose facilities are proposed: |
| |
| common_type |
| ratio |
| |
| And 5 time/duration/clock facilities are proposed |
| |
| duration |
| time_point |
| system_clock |
| monotonic_clock <font color="#c80000">// optional</font> |
| high_resolution_clock <font color="#c80000">// optional</font> |
| |
| Much thanks to Andrei Alexandrescu, |
| Walter Brown, |
| Peter Dimov, |
| Jeff Garland, |
| Terry Golubiewski, |
| Daniel Krügler, |
| Anthony Williams. |
| |
| Synopsis |
| |
| namespace std |
| { |
| |
| <font color="#c80000">// <type_traits></font> |
| |
| <font color="#c80000">// common_type</font> |
| |
| <font color="#c80000">// common_type is ageneral purpose trait that can be specialized for user-defined types.</font> |
| <font color="#c80000">// The semantics are intended to be identical to finding the resulting type of a</font> |
| <font color="#c80000">// the conditional operator.</font> |
| <font color="#c80000">// The client may need to specialize common_type if he wishes to convert to or from</font> |
| <font color="#c80000">// another type only explicitly. It is used to determine the result type</font> |
| <font color="#c80000">// in "mixed-mode" duration and time_point arithmetic. It will also find use in</font> |
| <font color="#c80000">// similar "mixed-mode" arithmetic applications.</font> |
| |
| template <class T, class U> |
| struct common_type |
| { |
| private: |
| static T t(); |
| static U u(); |
| public: |
| typedef decltype(true ? t() : u()) type; |
| }; |
| |
| <font color="#c80000">// or...</font> |
| |
| template <class ...T> struct common_type; |
| |
| template <class T> |
| struct common_type<T> |
| { |
| typedef T type; |
| }; |
| |
| template <class T, class U> |
| struct common_type<T, U> |
| { |
| private: |
| static T t(); |
| static U u(); |
| public: |
| typedef decltype(true ? t() : u()) type; |
| }; |
| |
| template <class T, class U, class ...V> |
| struct common_type<T, U, V...> |
| { |
| typedef typename common_type<typename common_type<T, U>::type, V...>::type type; |
| }; |
| |
| <font color="#c80000">// This alternative variadic formulation of common_type has some advantages:</font> |
| <font color="#c80000">//</font> |
| <font color="#c80000">// 1. The obvious advantage is that it can handle 3 or more arguments seamlessly.</font> |
| <font color="#c80000">// This can come in handy when writing template functions that take more than</font> |
| <font color="#c80000">// two arguments, such as fma(x, y, z).</font> |
| <font color="#c80000">//</font> |
| <font color="#c80000">// 2. We could just get rid of identity (avoiding the legacy conflict) and use</font> |
| <font color="#c80000">// common_type<T>::type in the one place we use identity<T>::type today.</font> |
| <font color="#c80000">//</font> |
| <font color="#c80000">// 3. For clients that need to specialize common_type (such as duration and time_point),</font> |
| <font color="#c80000">// the client still needs to specialize only the two-argument version. The default</font> |
| <font color="#c80000">// definition of the higher-order common_type will automatically use the client's</font> |
| <font color="#c80000">// specialized two-argument version.</font> |
| <font color="#c80000">// For example:</font> |
| <font color="#c80000">// common_type<duration<double>, hours, microseconds>::type is duration<double, micro></font> |
| |
| <font color="#c80000">// ... end or</font> |
| |
| <font color="#c80000">// The cost of not including either version of common_type is that it is very likely that</font> |
| <font color="#c80000">// the implementation would include it anyway, but spell it __common_type instead. This</font> |
| <font color="#c80000">// would prevent authors of arithmetic emulators from using their classes as representations</font> |
| <font color="#c80000">// with durations unless the emulator had exactly one implicit conversion to or from an</font> |
| <font color="#c80000">// arithmetic type. This would be a large loss of functionality from the client's point</font> |
| <font color="#c80000">// of view, possibly mandating a less safe interface for the client's arithmetic emulator.</font> |
| |
| <font color="#c80000">// ratio</font> |
| |
| <font color="#c80000">// ratio is a general purpose type allowing one to easily and safely compute integral</font> |
| <font color="#c80000">// ratio values at compile time. The ratio class catches all errors (such as divide by</font> |
| <font color="#c80000">// zero and overflow) at compile time. It is used in the duration and time_point libraries</font> |
| <font color="#c80000">// to efficiently create units of time. It can also be used in other "quantity"</font> |
| <font color="#c80000">// libraries (both std-defined and user-defined), or anywhere there is an integral</font> |
| <font color="#c80000">// ratio which is known at compile time. The use of this utility can greatly reduce</font> |
| <font color="#c80000">// the chances of run time overflow because the ratio (and any ratios resulting from</font> |
| <font color="#c80000">// ratio arithmetic) are always reduced to lowest terms.</font> |
| |
| <font color="#c80000">// The cost of not including ratio would mean that the implementor would likely have this</font> |
| <font color="#c80000">// functionality anyway, but spell it __ratio instead. This would prevent the client from</font> |
| <font color="#c80000">// using ratio in his own code as demonstrated in the "User1" example. Furthermore duration</font> |
| <font color="#c80000">// would have to be templated on two long long's instead of on ratio like so:</font> |
| <font color="#c80000">//</font> |
| <font color="#c80000">// template <class Rep, long long N, long long D> duration.</font> |
| <font color="#c80000">//</font> |
| <font color="#c80000">// This would mean that clients wanting to build a custom duration type (say a nanosecond</font> |
| <font color="#c80000">// represented by a double) would have to write:</font> |
| <font color="#c80000">//</font> |
| <font color="#c80000">// duration<double, 1, 1000000000LL></font> |
| <font color="#c80000">//</font> |
| <font color="#c80000">// instead of:</font> |
| <font color="#c80000">//</font> |
| <font color="#c80000">// duration<double, nano></font> |
| <font color="#c80000">//</font> |
| <font color="#c80000">// This lack of syntatic niceness, along with the loss of functionality in the reuse of</font> |
| <font color="#c80000">// ratio in user-written code seems to indicate that the loss of ratio would be a sizeable</font> |
| <font color="#c80000">// loss to client code.</font> |
| |
| template <intmax_t N, intmax_t D = 1> |
| class ratio |
| { |
| <font color="#c80000">// For every possible value of N and D, abs(N) >= 0 and abs(D) > 0</font> |
| static_assert(__static_abs<N>::value >= 0, "ratio numerator is out of range"); |
| static_assert(__static_abs<D>::value > 0, "ratio denominator is out of range"); |
| public: |
| static const intmax_t num; <font color="#c80000">// Reduced by greatest common divisor of N and D, has sign of sign(N) * sign(D)</font> |
| static const intmax_t den; <font color="#c80000">// Reduced by greatest common divisor of N and D, always positive</font> |
| <font color="#c80000">// When num == 0, den == 1</font> |
| }; |
| |
| <font color="#c80000">// The static_asserts in ratio are there to catch any values which have a negative absolute value.</font> |
| <font color="#c80000">// In a typical 2's complement representation this is only LLONG_MIN. The reason for prohibiting</font> |
| <font color="#c80000">// this value is because ratio must take the absolute values of its arguments and generally depends</font> |
| <font color="#c80000">// on that number being non-negative in order to maintain invariants such as den > 0.</font> |
| |
| <font color="#c80000">// convenience typedefs</font> |
| |
| typedef ratio<1, 1000000000000000000000000> yocto; <font color="#c80000">// conditionally supported</font> |
| typedef ratio<1, 1000000000000000000000> zepto; <font color="#c80000">// conditionally supported</font> |
| typedef ratio<1, 1000000000000000000> atto; |
| typedef ratio<1, 1000000000000000> femto; |
| typedef ratio<1, 1000000000000> pico; |
| typedef ratio<1, 1000000000> nano; |
| typedef ratio<1, 1000000> micro; |
| typedef ratio<1, 1000> milli; |
| typedef ratio<1, 100> centi; |
| typedef ratio<1, 10> deci; |
| typedef ratio< 10, 1> deca; |
| typedef ratio< 100, 1> hecto; |
| typedef ratio< 1000, 1> kilo; |
| typedef ratio< 1000000, 1> mega; |
| typedef ratio< 1000000000, 1> giga; |
| typedef ratio< 1000000000000, 1> tera; |
| typedef ratio< 1000000000000000, 1> peta; |
| typedef ratio< 1000000000000000000, 1> exa; |
| typedef ratio< 1000000000000000000000, 1> zetta; <font color="#c80000">// conditionally supported</font> |
| typedef ratio<1000000000000000000000000, 1> yotta; <font color="#c80000">// conditionally supported</font> |
| |
| <font color="#c80000">// Compile time arithmetic and comparisons should either avoid overflow or not compile</font> |
| |
| template <class R1, class R2> |
| requires R1 and R2 are instantiations of ratio |
| struct ratio_add |
| { |
| typedef ratio<pseudo code: R1 + R2> type; |
| }; |
| |
| template <class R1, class R2> |
| requires R1 and R2 are instantiations of ratio |
| struct ratio_subtract |
| { |
| typedef ratio<pseudo code: R1 - R2> type; |
| }; |
| |
| template <class R1, class R2> |
| requires R1 and R2 are instantiations of ratio |
| struct ratio_multiply |
| { |
| typedef ratio<pseudo code: R1 * R2> type; |
| }; |
| |
| template <class R1, class R2> |
| requires R1 and R2 are instantiations of ratio |
| struct ratio_divide |
| { |
| typedef ratio<pseudo code: R1 / R2> type; |
| }; |
| |
| template <class R1, class R2> |
| requires R1 and R2 are instantiations of ratio |
| struct ratio_equal |
| : public integral_constant<bool, pseudo code: R1 == R2> {}; |
| |
| template <class R1, class R2> |
| requires R1 and R2 are instantiations of ratio |
| struct ratio_not_equal |
| : public integral_constant<bool, !ratio_equal<R1, R2>::value> {}; |
| |
| template <class R1, class R2> |
| requires R1 and R2 are instantiations of ratio |
| struct ratio_less |
| : public integral_constant<bool, pseudo code: R1 < R2> {}; |
| |
| template <class R1, class R2> |
| requires R1 and R2 are instantiations of ratio |
| struct ratio_less_equal |
| : public integral_constant<bool, !ratio_less<R2, R1>::value> {}; |
| |
| template <class R1, class R2> |
| requires R1 and R2 are instantiations of ratio |
| struct ratio_greater |
| : public integral_constant<bool, ratio_less<R2, R1>::value> {}; |
| |
| template <class R1, class R2> |
| requires R1 and R2 are instantiations of ratio |
| struct ratio_greater_equal |
| : public integral_constant<bool, !ratio_less<R1, R2>::value> {}; |
| |
| namespace datetime |
| { |
| |
| <font color="#c80000">// duration customization traits</font> |
| |
| <font color="#c80000">// Authors of arithmetic emulation types should specialize treat_as_floating_point</font> |
| <font color="#c80000">// if their class emulates floating point and they want to use it as a duration's</font> |
| <font color="#c80000">// representation.</font> |
| |
| template <class Rep> struct treat_as_floating_point |
| : is_floating_point<Rep> {}; |
| |
| <font color="#c80000">// Authors of arithmetic emulation types should specialize duration_values</font> |
| <font color="#c80000">// if they want to use it as a duration's representation, and the default</font> |
| <font color="#c80000">// definition of duration_values does not have the correct behavior.</font> |
| |
| template <class Rep> |
| struct duration_values |
| { |
| public: |
| static constexpr Rep zero() {return Rep(0);} |
| static constexpr Rep max() {return numeric_limits<Rep>::max();} |
| static constexpr Rep min() {return -max();} |
| }; |
| |
| <font color="#c80000">// Note: Rep(0) instead of Rep() is used for zero() because the author of Rep may</font> |
| <font color="#c80000">// chose to have Rep() refer to an inderminant or unitialized value.</font> |
| |
| <font color="#c80000">// duration</font> |
| |
| <font color="#c80000">// A duration has a representation and a period.</font> |
| <font color="#c80000">// </font> |
| <font color="#c80000">// The representation is an arithmetic type, or a class emulating an arithmetic type.</font> |
| <font color="#c80000">//</font> |
| <font color="#c80000">// The period is the rational number of seconds between "ticks" of the duration. The</font> |
| <font color="#c80000">// duration simply holds a count of the elapsed number of ticks (using the</font> |
| <font color="#c80000">// representation), and that is related to seconds by multiplying by the period.</font> |
| <font color="#c80000">// Note, this multiplication is only required when one needs to convert between</font> |
| <font color="#c80000">// durations with different tick periods (e.g. milliseconds to microseconds).</font> |
| <font color="#c80000">// </font> |
| <font color="#c80000">// A duration has defalt construction and default copy semantics. One can also explicitly</font> |
| <font color="#c80000">// construct a duration from its representation or something implicitly convertible to</font> |
| <font color="#c80000">// its representation. If the representation is integral (or emulated integral) the</font> |
| <font color="#c80000">// duration may not be constructed from a floating point (or emulated floating point)</font> |
| <font color="#c80000">// type, even if that type is impilcitly convertible to the representation (the client</font> |
| <font color="#c80000">// must explicitly convert such an argument as they pass it to the constructor if such</font> |
| <font color="#c80000">// a conversion is desired).</font> |
| <font color="#c80000">// </font> |
| <font color="#c80000">// A duration may be implicitly constructible from another duration if the representations</font> |
| <font color="#c80000">// of the two durations meet certain requirements. Let the representation of this duration</font> |
| <font color="#c80000">// be Rep1 and the representation of the other duration be Rep2. Example representations</font> |
| <font color="#c80000">// include int, long long, double, or a user-defined class which emulates one of these</font> |
| <font color="#c80000">// arithmetic types. To qualify for implicit constructability Rep1 must be explicitly</font> |
| <font color="#c80000">// constructible from Rep2. Note that implicit constructibility of Rep1 from Rep2 is not</font> |
| <font color="#c80000">// required for this implicit construction between durations. Additionally the trait</font> |
| <font color="#c80000">// common_type<Rep1, Rep2>::type must be well defined. If a conditional expression involving</font> |
| <font color="#c80000">// these two types isn't valid, there must exist a common_type specialization which makes</font> |
| <font color="#c80000">// the trait valid.</font> |
| <font color="#c80000">// </font> |
| <font color="#c80000">// The requirements put on the relationship between Rep1 and Rep2 are intended to be minimal,</font> |
| <font color="#c80000">// and not require implicit conversions (which could be considered error prone by the author</font> |
| <font color="#c80000">// of either of these representations).</font> |
| <font color="#c80000">// </font> |
| <font color="#c80000">// In addition to the above relationship between the representations, implicit constructability</font> |
| <font color="#c80000">// also depends on whether the representation is considered floating point (or emulated floating</font> |
| <font color="#c80000">// point) or integral (or emulated integral).</font> |
| <font color="#c80000">// </font> |
| <font color="#c80000">// If a duration has a floating point (or emulated floating point) representation it</font> |
| <font color="#c80000">// is implicitly constructible from all other durations of any period (as long as</font> |
| <font color="#c80000">// the representations are compatible as described above).</font> |
| <font color="#c80000">// </font> |
| <font color="#c80000">// If a duration has an integral (or emulated integral) representation it is implicitly</font> |
| <font color="#c80000">// constructible from other integral-based durations which have a period which will exactly convert</font> |
| <font color="#c80000">// to the period of this duration with no truncation error. More specifically, if the</font> |
| <font color="#c80000">// period of this duration is P1, and the period of the other duration is P2, this</font> |
| <font color="#c80000">// duration is implicitly constructible from the other duration if P2/P1 is a whole number</font> |
| <font color="#c80000">// (as long as the representations are compatible as described above). Example:</font> |
| <font color="#c80000">// microseconds has a period p1 = 1/1000000 seconds. milliseconds has a period</font> |
| <font color="#c80000">// P2 = 1/1000 seconds. P2/P1 is (1/1000)/(1/1000000) = 1000000/1000 = 1000.</font> |
| <font color="#c80000">// Therefore microseconds will implicitly construct from milliseconds (but not vice-versa).</font> |
| <font color="#c80000">//</font> |
| <font color="#c80000">// These rules involving integral representations are meant to prevent accidental truncatation</font> |
| <font color="#c80000">// error. If truncation error is desired, a duration_cast facility is available to force it.</font> |
| <font color="#c80000">// Example:</font> |
| <font color="#c80000">// milliseconds ms(3); // ok, ms.count() == 3, which is 0.003 seconds</font> |
| <font color="#c80000">// microseconds us = ms; // ok, us.count() == 3000 which is 0.003000 seconds</font> |
| <font color="#c80000">// ++us; // ok, us.count() == 3001 which is 0.003001 seconds</font> |
| <font color="#c80000">// ms = us; // won't compile, might truncate</font> |
| <font color="#c80000">// ms = duration_cast<milliseconds>(us); // ok, ms.count() = 3, truncated a microsecond</font> |
| <font color="#c80000">// </font> |
| <font color="#c80000">// A duration has a single observer: rep count() const; which returns the stored</font> |
| <font color="#c80000">// representation which holds the number of elapsed "ticks".</font> |
| <font color="#c80000">// </font> |
| <font color="#c80000">// A duration supports the following member arithmetic:</font> |
| <font color="#c80000">// </font> |
| <font color="#c80000">// duration operator+() const;</font> |
| <font color="#c80000">// duration operator-() const;</font> |
| <font color="#c80000">// duration& operator++();</font> |
| <font color="#c80000">// duration operator++(int);</font> |
| <font color="#c80000">// duration& operator--();</font> |
| <font color="#c80000">// duration operator--(int);</font> |
| <font color="#c80000">// </font> |
| <font color="#c80000">// duration& operator+=(duration d);</font> |
| <font color="#c80000">// duration& operator-=(duration d);</font> |
| <font color="#c80000">// </font> |
| <font color="#c80000">// duration& operator*=(rep rhs);</font> |
| <font color="#c80000">// duration& operator/=(rep rhs);</font> |
| <font color="#c80000">//</font> |
| <font color="#c80000">// The arithmetic simply manipulates the "tick" count in the obvious way (e.g. operator++</font> |
| <font color="#c80000">// increments the tick count by 1).</font> |
| <font color="#c80000">// </font> |
| <font color="#c80000">// A duration supports the following non-member arithmetic.</font> |
| <font color="#c80000">// Let D1 represent duration<Rep1, Period1> and D2 represent duration<Rep2, Period2>.</font> |
| <font color="#c80000">// </font> |
| <font color="#c80000">// common_type<D1, D2>::type operator+( D1, D2); // returns a duration</font> |
| <font color="#c80000">// common_type<D1, D2>::type operator-( D1, D2); // returns a duration</font> |
| <font color="#c80000">// duration<common_type<D1::rep,Rep2>::type, D1::period> operator*( D1, Rep2); // returns a duration</font> |
| <font color="#c80000">// duration<common_type<D1::rep,Rep2>::type, D1::period> operator*(Rep2, D1); // returns a duration</font> |
| <font color="#c80000">// duration<common_type<D1::rep,Rep2>::type, D1::period> operator/( D1, Rep2); // returns a duration</font> |
| <font color="#c80000">// common_type<D1::rep, D2::rep>::type operator/( D1, D2); // returns a scalar</font> |
| <font color="#c80000">// </font> |
| <font color="#c80000">// A duration D1 is fully equality and less-than comparable with any other duration D2, as</font> |
| <font color="#c80000">// long as common_type<D1::rep, D2::rep> is well defined.</font> |
| <font color="#c80000">// Example:</font> |
| <font color="#c80000">// milliseconds ms(3); // ms.count() == 3, which is 0.003 seconds</font> |
| <font color="#c80000">// microseconds us = ms; // us.count() == 3000 which is 0.003000 seconds</font> |
| <font color="#c80000">// --us; // us.count() == 2999 which is 0.002999 seconds</font> |
| <font color="#c80000">// assert(ms != us); // 3 milliseconds is not equal to 2999 microseconds</font> |
| <font color="#c80000">// assert(ms > us); // 3 milliseconds is greater than 2999 microseconds</font> |
| <font color="#c80000">// ++us; // us.count() == 3000 which is 0.003000 seconds</font> |
| <font color="#c80000">// assert(ms == us); // 3 milliseconds is equal to 3000 microseconds</font> |
| <font color="#c80000">//</font> |
| <font color="#c80000">// Durations based on floating point representations are subject to round off error precisely the</font> |
| <font color="#c80000">// same way their representations are.</font> |
| <font color="#c80000">// </font> |
| <font color="#c80000">// Arithmetic and comparisons among integral-based durations is not subject to truncation error or</font> |
| <font color="#c80000">// round off error. If truncation error would result from the arithmetic (say</font> |
| <font color="#c80000">// by converting a smaller period duration to a larger one) the expression will</font> |
| <font color="#c80000">// not compile (unless duration_cast is used). If one performs arithmetic</font> |
| <font color="#c80000">// involving the duration's representation (such as division), then truncation</font> |
| <font color="#c80000">// will happen implicitly.</font> |
| <font color="#c80000">// </font> |
| <font color="#c80000">// Overflow error may silently happen with a duration. The std-defined durations</font> |
| <font color="#c80000">// have a minimum range of +/- 292 years.</font> |
| <font color="#c80000">// </font> |
| <font color="#c80000">// A duration is a thin wrapper around its representation. sizeof(duration<Rep, Period>) == sizeof(Rep).</font> |
| <font color="#c80000">// </font> |
| <font color="#c80000">// A duration can represent units as small as 10^-18 seconds (attoseconds) and as large as 10^18 seconds</font> |
| <font color="#c80000">// (about 30 billion years). The range of a duration is based on the range of its representation</font> |
| <font color="#c80000">// combined with its period.</font> |
| |
| <font color="#c80000">// The cost of not including the flexibility to represent different "tick periods" in the duration</font> |
| <font color="#c80000">// type would be a great loss of both flexibility, convenience and safety for the client. For example</font> |
| <font color="#c80000">// if had just one duration type which counted nanoseconds (no matter how that count was represented),</font> |
| <font color="#c80000">// then clients could never have the ability to traffic in picoseconds. And the only hope of reaching</font> |
| <font color="#c80000">// beyond a +/- 292 year range with nanoseconds is to increase the number of bits in the representation</font> |
| <font color="#c80000">// (such as a long long). Furthermore, if the client wanted to traffic in units larger than a nanosecond</font> |
| <font color="#c80000">// (e.g. seconds) for convience, they would likely need to set up their own conversion constants and</font> |
| <font color="#c80000">// convert manually.</font> |
| <font color="#c80000">//</font> |
| <font color="#c80000">// If the conversion constants are specified at run time, rather than as compile time integral constants,</font> |
| <font color="#c80000">// then the client suffers a significant performance penalty as for every conversion one will have to</font> |
| <font color="#c80000">// perform both a multiplication and a division. In contrast, when converting among any two units of</font> |
| <font color="#c80000">// the set (hours, minutes, seconds, milliseconds, microseconds, nanoseconds), there need be only a</font> |
| <font color="#c80000">// single multiplication *or* division (never both). This proposal makes every unit conversion as</font> |
| <font color="#c80000">// efficient as if it had been coded by hand (see duration_cast). Furthermore duration_cast encapsulates</font> |
| <font color="#c80000">// all unit conversions within a single uniform-syntax function which is easily used in generic code. There</font> |
| <font color="#c80000">// is no need (or motivation) to set up a "hub-and-spoke" conversion regimen, so that the number of conversion</font> |
| <font color="#c80000">// functions is O(N) rather than O(N^2).</font> |
| |
| template <class Rep, class Period = ratio<1>> |
| requires Rep is an arithmetic type, or a class emulating an arithmetic type, |
| and not an instantiation of duration |
| requires Period is an instantiation of ratio and represents a positive fraction |
| class duration |
| { |
| public: |
| typedef Rep rep; |
| typedef Period period; |
| private: |
| rep rep_; <font color="#c80000">// exposition only</font> |
| public: |
| <font color="#c80000">// construction / destruction</font> |
| duration() = default; |
| template <class Rep2> |
| requires is_convertible<Rep2, rep>::value && |
| (treat_as_floating_point<rep>::value || |
| !treat_as_floating_point<rep>::value && !treat_as_floating_point<Rep2>::value) |
| explicit duration(const Rep2& r); |
| ~duration() = default; |
| |
| <font color="#c80000">// copy semantics</font> |
| duration(const duration&) = default; |
| duration& operator=(const duration&) = default; |
| |
| <font color="#c80000">// conversions</font> |
| template <class Rep2, class Period2> |
| requires Rep2 is explicitly convertible to rep && |
| (treat_as_floating_point<rep>::value || |
| !treat_as_floating_point<Rep2>::value && ratio_divide<Period2, period>::type::den == 1) |
| duration(const duration<Rep2, Period2>& d); |
| |
| <font color="#c80000">// observer</font> |
| |
| rep count() const; |
| |
| <font color="#c80000">// arithmetic</font> |
| |
| duration operator+() const; |
| duration operator-() const; |
| duration& operator++(); |
| duration operator++(int); |
| duration& operator--(); |
| duration operator--(int); |
| |
| duration& operator+=(const duration& d); |
| duration& operator-=(const duration& d); |
| |
| duration& operator*=(const rep& rhs); |
| duration& operator/=(const rep& rhs); |
| |
| <font color="#c80000">// special values</font> |
| |
| static constexpr duration zero(); |
| static constexpr duration min(); |
| static constexpr duration max(); |
| }; |
| |
| <font color="#c80000">// convenience typedefs</font> |
| |
| typedef duration<int_least64_t, nano> nanoseconds; <font color="#c80000">// 10^-9 seconds</font> |
| typedef duration<int_least55_t, micro> microseconds; <font color="#c80000">// 10^-6 seconds</font> |
| typedef duration<int_least45_t, milli> milliseconds; <font color="#c80000">// 10^-3 seconds</font> |
| typedef duration<int_least35_t > seconds; <font color="#c80000">// 1 second</font> |
| typedef duration<int_least29_t, ratio< 60>> minutes; <font color="#c80000">// 60 seconds</font> |
| typedef duration<int_least23_t, ratio<3600>> hours; <font color="#c80000">// 3600 seconds</font> |
| |
| <font color="#c80000">// duration_cast can be used to force a conversion between two durations (assuming</font> |
| <font color="#c80000">// the source representation can be explicitly converted to the target representation).</font> |
| <font color="#c80000">// Not all integral-based durations are implicitly convertible to another (to</font> |
| <font color="#c80000">// avoid accidental truncation error). When truncation error is desired, the client</font> |
| <font color="#c80000">// uses duration_cast to explicitly request the non-exact conversion. When</font> |
| <font color="#c80000">// duration_cast is used to convert between durations which have an implicit conversion,</font> |
| <font color="#c80000">// the behavior and performance of the conversion using duration_cast is identical to</font> |
| <font color="#c80000">// that of the implicit conversion.</font> |
| |
| template <class ToDuration, class Rep, class Period> |
| requires ToDuration is an instantiation of duration |
| ToDuration duration_cast(const duration<Rep, Period>& fd); |
| |
| <font color="#c80000">// Examples:</font> |
| <font color="#c80000">// microseconds us(3500); // 3500 microseconds</font> |
| <font color="#c80000">// milliseconds ms = us; // Does not compile (implicit truncation)</font> |
| <font color="#c80000">// milliseconds ms = duration_cast<milliseconds>(us); // 3 milliseconds (explicit truncation)</font> |
| <font color="#c80000">// us = ms; // 3000 microseconds</font> |
| <font color="#c80000">// us = duration_cast<microseconds>(ms); // 3000 microseconds</font> |
| |
| } <font color="#c80000">// datetime</font> |
| |
| <font color="#c80000">// Given two durations: duration<Rep1, Period1> and duration<Rep2, Period2>, the common_type</font> |
| <font color="#c80000">// of those two durations is a duration with a representation of common_type<Rep1, Rep2>,</font> |
| <font color="#c80000">// and a period which is the "greatest common period" of Period1 and Period2. The GCP</font> |
| <font color="#c80000">// (Greatest Common Period) of Period1 and Period2 is the largest period which will divide</font> |
| <font color="#c80000">// both Period1 and Period2 evenly (and is often equivalent to the minimum of Period1 and</font> |
| <font color="#c80000">// Period2). This can be computed (by the implementation at compile time) by</font> |
| <font color="#c80000">// GCD(Period1::num, Period2::num) / LCM(Period1::den, Period2::den) where GCD is</font> |
| <font color="#c80000">// "Greatest Common Divisor" and LCM is "Least Common Multiple".</font> |
| |
| template <class Rep1, class Period1, class Rep2, class Period2> |
| struct common_type<datetime::duration<Rep1, Period1>, datetime::duration<Rep2, Period2> > |
| { |
| typedef datetime::duration<typename common_type<Rep1, Rep2>::type, |
| ratio<GCD(Period1::num, Period2::num), LCM(Period1::den, Period2::den)>> type; |
| }; |
| |
| <font color="#c80000">// Note: For any two durations D1 and D2, they will both exactly convert to common_type<D1, D2>::type.</font> |
| <font color="#c80000">// common_type<D1, D2>::type will have the largest possible period to make this possible, and</font> |
| <font color="#c80000">// may be the same type as D1 or D2. Examples:</font> |
| <font color="#c80000">// common_type<minutes, microseconds>::type is microseconds.</font> |
| <font color="#c80000">// common_type<milliseconds, microseconds>::type is microseconds.</font> |
| <font color="#c80000">// common_type<nanoseconds, microseconds>::type is nanoseconds.</font> |
| <font color="#c80000">//</font> |
| <font color="#c80000">// A more complex example:</font> |
| <font color="#c80000">// common_type< duration<long, milli>, duration<int, ratio<1,30>> >::type is</font> |
| <font color="#c80000">// duration<long, ratio<1,3000>>. And both duration<long, milli> and </font> |
| <font color="#c80000">// duration<int, ratio<1,30>> will exactly convert to duration<long, ratio<1,3000>>.</font> |
| <font color="#c80000">// The former multitplies its representation by 3L and the latter converts its</font> |
| <font color="#c80000">// representation to long and multiplies that result by 1000L. There exists no</font> |
| <font color="#c80000">// duration with a larger period such that both duration<long, milli> and</font> |
| <font color="#c80000">// duration<int, ratio<1,30>> will exactly convert to it.</font> |
| |
| namespace datetime { |
| |
| template <class Rep1, class Period1, class Rep2, class Period2> |
| bool operator==(const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs); |
| template <class Rep1, class Period1, class Rep2, class Period2> |
| bool operator!=(const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs); |
| template <class Rep1, class Period1, class Rep2, class Period2> |
| bool operator< (const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs); |
| template <class Rep1, class Period1, class Rep2, class Period2> |
| bool operator<=(const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs); |
| template <class Rep1, class Period1, class Rep2, class Period2> |
| bool operator> (const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs); |
| template <class Rep1, class Period1, class Rep2, class Period2> |
| bool operator>=(const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs); |
| |
| template <class Rep1, class Period1, class Rep2, class Period2> |
| typename common_type<duration<Rep1, Period1>, duration<Rep2, Period2> >::type |
| operator+(const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs); |
| |
| template <class Rep1, class Period1, class Rep2, class Period2> |
| typename common_type<duration<Rep1, Period1>, duration<Rep2, Period2> >::type |
| operator-(const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs); |
| |
| template <class Rep1, class Period, class Rep2> |
| requires Constructible<Rep1, typename common_type<Rep1, Rep2>::type>::value> && |
| Constructible<Rep2, typename common_type<Rep1, Rep2>::type>::value> |
| duration<typename common_type<Rep1, Rep2>::type, Period> |
| operator*(const duration<Rep, Period>& d, const Rep2& s); |
| |
| template <class Rep1, class Period, class Rep2> |
| requires Constructible<Rep1, typename common_type<Rep1, Rep2>::type>::value> && |
| Constructible<Rep2, typename common_type<Rep1, Rep2>::type>::value> |
| duration<typename common_type<Rep1, Rep2>::type, Period> |
| operator*(const Rep2& s, const duration<Rep, Period>& d); |
| |
| template <class Rep1, class Period, class Rep2> |
| requires Rep2 is not a duration && |
| Constructible<Rep1, typename common_type<Rep1, Rep2>::type>::value> && |
| Constructible<Rep2, typename common_type<Rep1, Rep2>::type>::value> |
| duration<typename common_type<Rep1, Rep2>::type, Period> |
| operator/(const duration<Rep, Period>& d, const Rep2& s); |
| |
| <font color="#c80000">// Note: the above 3 signatures can be approximated with is_convertible if concepts do not</font> |
| <font color="#c80000">// make it into the language. Requiring only *explicit* convertibility between the Rep</font> |
| <font color="#c80000">// types is strongly desired. One way or another, Rep2 must be constrained. Otherwise</font> |
| <font color="#c80000">// the operators are overly generic.</font> |
| |
| template <class Rep1, class Period1, class Rep2, class Period2> |
| typename common_type<Rep1, Rep2>::type |
| operator/(const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs); |
| |
| <font color="#c80000">// time_point</font> |
| |
| <font color="#c80000">// A time_point represents an epoch plus or minus a duration. The relationship between a time_point</font> |
| <font color="#c80000">// which represents "now" and the time_point's epoch is obtained via a clock. Each time_point is</font> |
| <font color="#c80000">// tied to a specific clock. Thus, for any time_point, one can find the duration between that</font> |
| <font color="#c80000">// point in time and now, and between that point in time, and its epoch.</font> |
| <font color="#c80000">// </font> |
| <font color="#c80000">// A time_point may be default constructed. This time_point represents the epoch. time_point has</font> |
| <font color="#c80000">// default copy semantics.</font> |
| <font color="#c80000">// </font> |
| <font color="#c80000">// time_point may be explicitly constructed by a duration having the same representation and period as</font> |
| <font color="#c80000">// the time_point. Any other duration which is implicitly convertible to the time_point's "native" duration can</font> |
| <font color="#c80000">// also be used to explicitly construct the time_point. The meaning of this construction is identical to</font> |
| <font color="#c80000">// time_point() + d.</font> |
| <font color="#c80000">//</font> |
| <font color="#c80000">// A time_point is implicitly constructible from another time_point if they share the same clock,</font> |
| <font color="#c80000">// and the duration of this time_point is implicitly constructible from the duration of the other</font> |
| <font color="#c80000">// time_point. A time_point constructed in this fashion will compare equal to the source time_point</font> |
| <font color="#c80000">// after the construction.</font> |
| <font color="#c80000">// </font> |
| <font color="#c80000">// A time_point supports the following member arithmetic:</font> |
| <font color="#c80000">// </font> |
| <font color="#c80000">// time_point& operator+=(duration d);</font> |
| <font color="#c80000">// time_point& operator-=(duration d);</font> |
| <font color="#c80000">// </font> |
| <font color="#c80000">// A time_point supports the following non-member arithmetic.</font> |
| <font color="#c80000">// Let T1 represent time_point<Clock, Duration1>,</font> |
| <font color="#c80000">// T2 represent time_point<Clock, Duration2>,</font> |
| <font color="#c80000">// and D represent duration<Rep3, Period3>. Note that T1 and T2 must have the same Clock.</font> |
| <font color="#c80000">// Attempts to interoperate times having different clocks results in a compile time failure.</font> |
| <font color="#c80000">// </font> |
| <font color="#c80000">// T2 operator+(T1, D); // return type is a time_point</font> |
| <font color="#c80000">// T2 operator+( D, T1); // return type is a time_point</font> |
| <font color="#c80000">// T2 operator-(T1, D); // return type is a time_point</font> |
| <font color="#c80000">// D operator-(T1, T2); // return type is a duration</font> |
| <font color="#c80000">// </font> |
| <font color="#c80000">// A time_point T1 is fully equality and less-than comparable with any other time_point T2 which</font> |
| <font color="#c80000">// has the same clock, and for which their durations are comparable.</font> |
| <font color="#c80000">// </font> |
| <font color="#c80000">// Times based on floating point representations are subject to round off error precisely the</font> |
| <font color="#c80000">// same way their representations are.</font> |
| <font color="#c80000">// </font> |
| <font color="#c80000">// Times based on integral representations are not subject to truncation error or round off</font> |
| <font color="#c80000">// error. A compile time error will result if truncation error is possible. Truncation error</font> |
| <font color="#c80000">// is only possible with construction or the member arithmetic (and won't compile). Non-member</font> |
| <font color="#c80000">// arithmetic and comparison is always exact. Overflow error with integral based times remains a</font> |
| <font color="#c80000">// possibility.</font> |
| <font color="#c80000">// </font> |
| <font color="#c80000">// A time_point is a thin wrapper around its representation.</font> |
| <font color="#c80000">// sizeof(time_point<Clock, Duration>) == sizeof(Duration) == sizeof(Duration::rep).</font> |
| <font color="#c80000">// </font> |
| <font color="#c80000">// A time_point can represent units as small as 10^-18 seconds and as large as 10^18 seconds. The range</font> |
| <font color="#c80000">// of a time_point is based on the range of its representation combined with its period.</font> |
| <font color="#c80000">//</font> |
| <font color="#c80000">// Because no two clocks report the exact same time, even clocks which nominally have the same</font> |
| <font color="#c80000">// epoch, are considered by this framework to have different epochs, if only by a few nanoseconds.</font> |
| <font color="#c80000">// Converting time_points from one clock to another will involve synchronization of the clocks,</font> |
| <font color="#c80000">// which can be viewed as a synchronization of their epochs. Such synchronization is clock specific</font> |
| <font color="#c80000">// and beyond the scope of this API. A future API, or a platform specific API, can easily</font> |
| <font color="#c80000">// write such a synchronization API, basing it on this API.</font> |
| |
| <font color="#c80000">// The cost of not including a time_point class is the lack of the ability to safely interact with</font> |
| <font color="#c80000">// the concept of "epoch + duration". Without a separate type, the client is in danger of accidently</font> |
| <font color="#c80000">// writing code that boils down to "epoch1 + duration1" + "epoch2 + duration2". Algebraically this</font> |
| <font color="#c80000">// results in epoch1+epoch2 as a subexpression which is likely to be completely without meaning. What</font> |
| <font color="#c80000">// would it mean to add New Years 1970 to the point in time at which your computer booted up? Or for</font> |
| <font color="#c80000">// that matter, what is the meaning of "New Years 1970" + "New Years 1970"?</font> |
| <font color="#c80000">//</font> |
| <font color="#c80000">// Additionally this would force the duration type to play double duty as a time_point leading to</font> |
| <font color="#c80000">// client confusion. For example POSIX has timespec represent a duration in nanosleep, and yet the</font> |
| <font color="#c80000">// same type is used as a time_point in pthread_cond_timedwait and pthread_mutex_timedlock. The</font> |
| <font color="#c80000">// confusion seems even more likely with a function such as clock_nanosleep where timespec can mean</font> |
| <font color="#c80000">// either a duration or a time_point depending upon another argument to the function.</font> |
| <font color="#c80000">//</font> |
| <font color="#c80000">// In C++ we can easily mitigate such errors by detecting them at compile time. This is done through</font> |
| <font color="#c80000">// the use of distinct types for these distinct concepts (even though both types have identical layout!).</font> |
| |
| template <class Clock, class Duration = typename Clock::duration> |
| requires Duration is an instantiation of duration |
| class time_point |
| { |
| public: |
| typedef Clock clock; |
| typedef Duration duration; |
| typedef typename duration::rep rep; |
| typedef typename duration::period period; |
| private: |
| duration d_; <font color="#c80000">// exposition only</font> |
| |
| public: |
| time_point(); <font color="#c80000">// has value "epoch"</font> |
| explicit time_point(const duration& d); <font color="#c80000">// same as time_point() + d</font> |
| |
| <font color="#c80000">// conversions</font> |
| template <class Duration2> |
| requires Convertible<Duration2, duration> |
| time_point(const time_point<clock, Duration2>& t); |
| |
| <font color="#c80000">// observer</font> |
| |
| duration time_since_epoch() const; |
| |
| <font color="#c80000">// arithmetic</font> |
| |
| time_point& operator+=(const duration& d); |
| time_point& operator-=(const duration& d); |
| |
| <font color="#c80000">// special values</font> |
| |
| static time_point min(); |
| static time_point max(); |
| }; |
| |
| } <font color="#c80000">// datetime</font> |
| |
| template <class Clock, class Duration1, class Duration2> |
| struct common_type<datetime::time_point<Clock, Duration1>, datetime::time_point<Clock, Duration2> > |
| { |
| typedef datetime::time_point<Clock, typename common_type<Duration1, Duration2>::type> type; |
| }; |
| |
| namespace datetime { |
| |
| template <class ToDuration, class Clock, class Duration> |
| time_point<Clock, ToDuration> time_point_cast(const time_point<Clock, Duration>& t); |
| |
| template <class Clock, class Duration1, class Duration2> |
| bool operator==(const time_point<Clock, Duration1>& lhs, const time_point<Clock, Duration2>& rhs); |
| template <class Clock, class Duration1, class Duration2> |
| bool operator!=(const time_point<Clock, Duration1>& lhs, const time_point<Clock, Duration2>& rhs); |
| template <class Clock, class Duration1, class Duration2> |
| bool operator< (const time_point<Clock, Duration1>& lhs, const time_point<Clock, Duration2>& rhs); |
| template <class Clock, class Duration1, class Duration2> |
| bool operator<=(const time_point<Clock, Duration1>& lhs, const time_point<Clock, Duration2>& rhs); |
| template <class Clock, class Duration1, class Duration2> |
| bool operator> (const time_point<Clock, Duration1>& lhs, const time_point<Clock, Duration2>& rhs); |
| template <class Clock, class Duration1, class Duration2> |
| bool operator>=(const time_point<Clock, Duration1>& lhs, const time_point<Clock, Duration2>& rhs); |
| |
| template <class Clock, class Duration1, class Rep2, class Period2> |
| time_point<Clock, typename common_type<Duration1, duration<Rep2, Period2> >::type> |
| operator+(const time_point<Clock, Duration1>& lhs, const duration<Rep2, Period2>& rhs); |
| |
| template <class Rep1, class Period1, class Clock, class Duration2> |
| time_point<Clock, typename common_type<duration<Rep1, Period1>, Duration2>::type> |
| operator+(const duration<Rep1, Period1>& lhs, const time_point<Clock, Duration2>& rhs); |
| |
| template <class Clock, class Duration1, class Rep2, class Period2> |
| time_point<Clock, typename common_type<Duration1, duration<Rep2, Period2> >::type> |
| operator-(const time_point<Clock, Duration1>& lhs, const duration<Rep2, Period2>& rhs); |
| |
| template <class Clock, class Duration1, class Duration2> |
| typename common_type<Duration1, Duration2>::type |
| operator-(const time_point<Clock, Duration1>& lhs, const time_point<Clock, Duration2>& rhs); |
| |
| <font color="#c80000">// clocks</font> |
| |
| <font color="#c80000">// A clock specifies a representation, and a period. These specifications are used to</font> |
| <font color="#c80000">// to define a clock's native duration and time_point types. A clock also has a function to get the current</font> |
| <font color="#c80000">// time_point. A clock need not have any state.</font> |
| |
| <font color="#c80000">// The cost of not including separate types for clocks is that there is no better place to</font> |
| <font color="#c80000">// bundle the "native" duration and time_point types for a clock with the functionality to</font> |
| <font color="#c80000">// get the current time_point (what time is it now?). By bundling this information into a</font> |
| <font color="#c80000">// type, the extension to support multiple clocks is both easy and obvious. The ability to</font> |
| <font color="#c80000">// easily support multiple clocks in such a flexible yet simple and efficient manner is</font> |
| <font color="#c80000">// very important. A client might (for example) write code with the clock as a generic</font> |
| <font color="#c80000">// template parameter, and then easily experiment with different timers.</font> |
| |
| class system_clock |
| { |
| public: |
| typedef <unspecified> rep; |
| typedef ratio<unspecified, unspecified> period; |
| typedef datetime::duration<rep, period> duration; |
| typedef datetime::time_point<system_clock> time_point; |
| static const bool is_mononontic = <unspecified>; |
| |
| static time_point now(); |
| |
| <font color="#c80000">// Map to C API</font> |
| static time_t to_time_t (const time_point& t); |
| static time_point from_time_t(time_t t); |
| }; |
| |
| class monotonic_clock <font color="#c80000">// optional</font> |
| { |
| public: |
| typedef <unspecified> rep; |
| typedef ratio<unspecified, unspecified> period; |
| typedef datetime::duration<rep, period> duration; |
| typedef datetime::time_point<monotonic_clock> time_point; |
| static const bool is_mononontic = true; |
| |
| static time_point now(); |
| }; |
| |
| class high_resolution_clock <font color="#c80000">// optional</font> |
| { |
| public: |
| typedef <unspecified> rep; |
| typedef ratio<unspecified, unspecified> period; |
| typedef datetime::duration<rep, period> duration; |
| typedef datetime::time_point<high_resolution_clock> time_point; |
| static const bool is_mononontic = <unspecified>; |
| |
| static time_point now(); |
| }; |
| |
| <font color="#c80000">// Note: These clocks may be three separate types, or typedefs to one or two common types.</font> |
| |
| } <font color="#c80000">// datetime</font> |
| |
| <font color="#c80000">//////////////////////////</font> |
| <font color="#c80000">// Threading interface //</font> |
| <font color="#c80000">//////////////////////////</font> |
| |
| <font color="#c80000">// timed_mutex</font> |
| |
| struct timed_mutex |
| { |
| public: |
| timed_mutex(); |
| ~timed_mutex(); |
| |
| timed_mutex(const timed_mutex&) = delete; |
| timed_mutex& operator=(const timed_mutex&) = delete; |
| |
| void lock(); |
| bool try_lock(); |
| template <class Rep, class Period> |
| bool try_lock_for(const datetime::duration<Rep, Period>& rel_time); |
| template <class Clock, class Duration> |
| bool try_lock_until(const datetime::time_point<Clock, Duration>& abs_time); |
| void unlock(); |
| |
| typedef unspecified native_handle_type; <font color="#c80000">// optional. example: pthread_mutex_t*</font> |
| native_handle_type native_handle(); <font color="#c80000">// optional</font> |
| }; |
| |
| <font color="#c80000">// recursive_timed_mutex</font> |
| |
| struct recursive_timed_mutex |
| { |
| public: |
| recursive_timed_mutex(); |
| ~recursive_timed_mutex(); |
| |
| recursive_timed_mutex(const recursive_timed_mutex&) = delete; |
| recursive_timed_mutex& operator=(const recursive_timed_mutex&) = delete; |
| |
| void lock(); |
| bool try_lock(); |
| template <class Rep, class Period> |
| bool try_lock_for(const datetime::duration<Rep, Period>& rel_time); |
| template <class Clock, class Duration> |
| bool try_lock_until(const datetime::time_point<Clock, Duration>& abs_time); |
| void unlock(); |
| |
| typedef unspecified native_handle_type; <font color="#c80000">// optional. example: pthread_mutex_t*</font> |
| native_handle_type native_handle(); <font color="#c80000">// optional</font> |
| }; |
| |
| <font color="#c80000">// unique_lock</font> |
| |
| template <class Mutex> |
| class unique_lock |
| { |
| public: |
| typedef Mutex mutex_type; |
| |
| unique_lock(); |
| explicit unique_lock(mutex_type& m); |
| unique_lock(mutex_type& m, defer_lock_t); |
| unique_lock(mutex_type& m, try_to_lock_t); |
| unique_lock(mutex_type& m, adopt_lock_t); |
| template <class Rep, class Period> |
| unique_lock(mutex_type& m, const datetime::duration<Rep, Period>& rel_t); |
| template <class Clock, class Duration> |
| unique_lock(mutex_type& m, const datetime::time_point<Clock, Duration>& abs_time); |
| ~unique_lock(); |
| |
| unique_lock(unique_lock const&) = delete; |
| unique_lock& operator=(unique_lock const&) = delete; |
| |
| unique_lock(unique_lock&& u); |
| unique_lock& operator=(unique_lock&& u); |
| |
| void lock(); |
| bool try_lock(); |
| template <class Rep, class Period> |
| bool try_lock_for(const datetime::duration<Rep, Period>& rel_t); |
| template <class Clock, class Duration> |
| bool try_lock_until(const datetime::time_point<Clock, Duration>& abs_time); |
| void unlock(); |
| |
| bool owns_lock() const; |
| operator unspecified-bool-type () const; |
| mutex_type* mutex() const; |
| |
| void swap(unique_lock&& u); |
| mutex_type* release(); |
| }; |
| |
| <font color="#c80000">// condition_variable</font> |
| |
| class condition_variable |
| { |
| public: |
| |
| condition_variable(); |
| ~condition_variable(); |
| |
| condition_variable(const condition_variable&) = delete; |
| condition_variable& operator=(const condition_variable&) = delete; |
| |
| void notify_one(); |
| void notify_all(); |
| |
| void wait(unique_lock<mutex>& lock); |
| template <class Predicate> |
| void wait(unique_lock<mutex>& lock, Predicate pred); |
| |
| template <class Clock, class Duration> |
| bool wait_until(unique_lock<mutex>& lock, |
| const datetime::time_point<Clock, Duration>& abs_time); |
| template <class Clock, class Duration, class Predicate> |
| bool wait_until(unique_lock<mutex>& lock, |
| const datetime::time_point<Clock, Duration>& abs_time, |
| Predicate pred); |
| |
| template <class Rep, class Period> |
| bool wait_for(unique_lock<mutex>& lock, const datetime::duration<Rep, Period>& rel_time); |
| template <class Rep, class Period, class Predicate> |
| bool wait_for(unique_lock<mutex>& lock, const datetime::duration<Rep, Period>& rel_time, |
| Predicate pred); |
| |
| typedef pthread_cond_t* native_handle_type; |
| native_handle_type native_handle(); |
| }; |
| |
| <font color="#c80000">// condition_variable_any</font> |
| |
| class condition_variable_any |
| { |
| public: |
| |
| condition_variable_any(); |
| ~condition_variable_any(); |
| |
| condition_variable_any(const condition_variable_any&) = delete; |
| condition_variable_any& operator=(const condition_variable_any&) = delete; |
| |
| void notify_one(); |
| void notify_all(); |
| |
| template <class Lock> |
| void wait(Lock& lock); |
| template <class Lock, class Predicate> |
| void wait(Lock& lock, Predicate pred); |
| |
| template <class Lock, class Clock, class Duration> |
| bool wait_until(Lock& lock, const datetime::time_point<Clock, Duration>& abs_time); |
| template <class Lock, class Clock, class Duration, class Predicate> |
| bool wait_until(Lock& lock, const datetime::time_point<Clock, Duration>& abs_time, |
| Predicate pred); |
| |
| template <class Lock, class Rep, class Period> |
| bool wait_for(Lock& lock, const datetime::duration<Rep, Period>& rel_time); |
| template <class Lock, class Rep, class Period, class Predicate> |
| bool wait_for(Lock& lock, const datetime::duration<Rep, Period>& rel_time, Predicate pred); |
| }; |
| |
| <font color="#c80000">// sleep</font> |
| |
| namespace this_thread |
| { |
| |
| template <class Rep, class Period> |
| void sleep_for(const datetime::duration<Rep, Period>& rel_time); |
| |
| template <class Clock, class Duration> |
| void sleep_until(const datetime::time_point<Clock, Duration>& abs_time); |
| |
| } <font color="#c80000">// this_thread</font> |
| |
| } <font color="#c80000">// std</font> |
| |
| */</font> |
| |
| #include <ctime> |
| #include <climits> |
| #include <inttypes.h> |
| #include <limits> |
| #include "type_traits" |
| |
| #define decltype __typeof__ |
| |
| namespace std |
| { |
| |
| <font color="#c80000">//////////////////////////////////////////////////////////</font> |
| <font color="#c80000">////////////////////// common_type ///////////////////////</font> |
| <font color="#c80000">//////////////////////////////////////////////////////////</font> |
| |
| #define VARIADIC_COMMON_TYPE 0 |
| |
| #if VARIADIC_COMMON_TYPE == 0 |
| |
| template <class T, class U> |
| struct common_type |
| { |
| private: |
| static T t(); |
| static U u(); |
| public: |
| typedef decltype(true ? t() : u()) type; |
| }; |
| |
| #else |
| |
| template <class ...T> struct common_type; |
| |
| template <class T> |
| struct common_type<T> |
| { |
| typedef T type; |
| }; |
| |
| template <class T, class U> |
| struct common_type<T, U> |
| { |
| private: |
| static T t(); |
| static U u(); |
| public: |
| typedef decltype(true ? t() : u()) type; |
| }; |
| |
| template <class T, class U, class ...V> |
| struct common_type<T, U, V...> |
| { |
| typedef typename common_type<typename common_type<T, U>::type, V...>::type type; |
| }; |
| |
| #endif |
| |
| <font color="#c80000">//////////////////////////////////////////////////////////</font> |
| <font color="#c80000">/////////////////////// ratio ////////////////////////////</font> |
| <font color="#c80000">//////////////////////////////////////////////////////////</font> |
| |
| <font color="#c80000">// __static_gcd</font> |
| |
| template <intmax_t X, intmax_t Y> |
| struct __static_gcd |
| { |
| static const intmax_t value = __static_gcd<Y, X % Y>::value; |
| }; |
| |
| template <intmax_t X> |
| struct __static_gcd<X, 0> |
| { |
| static const intmax_t value = X; |
| }; |
| |
| <font color="#c80000">// __static_lcm</font> |
| |
| template <intmax_t X, intmax_t Y> |
| struct __static_lcm |
| { |
| static const intmax_t value = X / __static_gcd<X, Y>::value * Y; |
| }; |
| |
| template <intmax_t X> |
| struct __static_abs |
| { |
| static const intmax_t value = X < 0 ? -X : X; |
| }; |
| |
| template <intmax_t X> |
| struct __static_sign |
| { |
| static const intmax_t value = X == 0 ? 0 : (X < 0 ? -1 : 1); |
| }; |
| |
| template <intmax_t X, intmax_t Y, intmax_t = __static_sign<Y>::value> |
| class __ll_add; |
| |
| template <intmax_t X, intmax_t Y> |
| class __ll_add<X, Y, 1> |
| { |
| static const intmax_t min = (1LL << (sizeof(intmax_t) * CHAR_BIT - 1)) + 1; |
| static const intmax_t max = -min; |
| |
| static char test[X <= max - Y]; |
| <font color="#c80000">// static_assert(X <= max - Y, "overflow in __ll_add");</font> |
| public: |
| static const intmax_t value = X + Y; |
| }; |
| |
| template <intmax_t X, intmax_t Y> |
| class __ll_add<X, Y, 0> |
| { |
| public: |
| static const intmax_t value = X; |
| }; |
| |
| template <intmax_t X, intmax_t Y> |
| class __ll_add<X, Y, -1> |
| { |
| static const intmax_t min = (1LL << (sizeof(intmax_t) * CHAR_BIT - 1)) + 1; |
| static const intmax_t max = -min; |
| |
| static char test[min - Y <= X]; |
| <font color="#c80000">// static_assert(min - Y <= X, "overflow in __ll_add");</font> |
| public: |
| static const intmax_t value = X + Y; |
| }; |
| |
| template <intmax_t X, intmax_t Y, intmax_t = __static_sign<Y>::value> |
| class __ll_sub; |
| |
| template <intmax_t X, intmax_t Y> |
| class __ll_sub<X, Y, 1> |
| { |
| static const intmax_t min = (1LL << (sizeof(intmax_t) * CHAR_BIT - 1)) + 1; |
| static const intmax_t max = -min; |
| |
| static char test[min + Y <= X]; |
| <font color="#c80000">// static_assert(min + Y <= X, "overflow in __ll_sub");</font> |
| public: |
| static const intmax_t value = X - Y; |
| }; |
| |
| template <intmax_t X, intmax_t Y> |
| class __ll_sub<X, Y, 0> |
| { |
| public: |
| static const intmax_t value = X; |
| }; |
| |
| template <intmax_t X, intmax_t Y> |
| class __ll_sub<X, Y, -1> |
| { |
| static const intmax_t min = (1LL << (sizeof(intmax_t) * CHAR_BIT - 1)) + 1; |
| static const intmax_t max = -min; |
| |
| static char test[X <= max + Y]; |
| <font color="#c80000">// static_assert(X <= max + Y, "overflow in __ll_sub");</font> |
| public: |
| static const intmax_t value = X - Y; |
| }; |
| |
| template <intmax_t X, intmax_t Y> |
| class __ll_mul |
| { |
| static const intmax_t nan = (1LL << (sizeof(intmax_t) * CHAR_BIT - 1)); |
| static const intmax_t min = nan + 1; |
| static const intmax_t max = -min; |
| static const intmax_t __a_x = __static_abs<X>::value; |
| static const intmax_t __a_y = __static_abs<Y>::value; |
| |
| static char test1[X != nan]; |
| static char test2[Y != nan]; |
| static char test[__a_x <= max / __a_y]; |
| <font color="#c80000">// static_assert(X != nan && Y != nan && __a_x <= max / __a_y, "overflow in __ll_mul");</font> |
| public: |
| static const intmax_t value = X * Y; |
| }; |
| |
| template <intmax_t Y> |
| class __ll_mul<0, Y> |
| { |
| public: |
| static const intmax_t value = 0; |
| }; |
| |
| template <intmax_t X> |
| class __ll_mul<X, 0> |
| { |
| public: |
| static const intmax_t value = 0; |
| }; |
| |
| template <> |
| class __ll_mul<0, 0> |
| { |
| public: |
| static const intmax_t value = 0; |
| }; |
| |
| <font color="#c80000">// Not actually used but left here in case needed in future maintenance</font> |
| template <intmax_t X, intmax_t Y> |
| class __ll_div |
| { |
| static const intmax_t nan = (1LL << (sizeof(intmax_t) * CHAR_BIT - 1)); |
| static const intmax_t min = nan + 1; |
| static const intmax_t max = -min; |
| |
| static char test1[X != nan]; |
| static char test2[Y != nan]; |
| static char test3[Y != 0]; |
| <font color="#c80000">// static_assert(X != nan && Y != nan && Y != 0, "overflow in __ll_div");</font> |
| public: |
| static const intmax_t value = X / Y; |
| }; |
| |
| template <intmax_t N, intmax_t D = 1> |
| class ratio |
| { |
| static char test1[__static_abs<N>::value >= 0]; |
| static char test2[__static_abs<D>::value > 0]; |
| <font color="#c80000">// static_assert(__static_abs<N>::value >= 0, "ratio numerator is out of range");</font> |
| <font color="#c80000">// static_assert(D != 0, "ratio divide by 0");</font> |
| <font color="#c80000">// static_assert(__static_abs<D>::value > 0, "ratio denominator is out of range");</font> |
| static const intmax_t __na = __static_abs<N>::value; |
| static const intmax_t __da = __static_abs<D>::value; |
| static const intmax_t __s = __static_sign<N>::value * __static_sign<D>::value; |
| static const intmax_t __gcd = __static_gcd<__na, __da>::value; |
| public: |
| static const intmax_t num = __s * __na / __gcd; |
| static const intmax_t den = __da / __gcd; |
| }; |
| |
| template <class T> struct ___is_ratio : tmp::false_type {}; |
| template <intmax_t N, intmax_t D> struct ___is_ratio<ratio<N, D> > : tmp::true_type {}; |
| template <class T> struct __is_ratio : ___is_ratio<typename tmp::remove_cv<T>::type> {}; |
| |
| typedef ratio<1LL, 1000000000000000000LL> atto; |
| typedef ratio<1LL, 1000000000000000LL> femto; |
| typedef ratio<1LL, 1000000000000LL> pico; |
| typedef ratio<1LL, 1000000000LL> nano; |
| typedef ratio<1LL, 1000000LL> micro; |
| typedef ratio<1LL, 1000LL> milli; |
| typedef ratio<1LL, 100LL> centi; |
| typedef ratio<1LL, 10LL> deci; |
| typedef ratio< 10LL, 1LL> deca; |
| typedef ratio< 100LL, 1LL> hecto; |
| typedef ratio< 1000LL, 1LL> kilo; |
| typedef ratio< 1000000LL, 1LL> mega; |
| typedef ratio< 1000000000LL, 1LL> giga; |
| typedef ratio< 1000000000000LL, 1LL> tera; |
| typedef ratio< 1000000000000000LL, 1LL> peta; |
| typedef ratio<1000000000000000000LL, 1LL> exa; |
| |
| template <class R1, class R2> |
| struct ratio_add |
| { |
| typedef ratio<__ll_add<__ll_mul<R1::num, R2::den>::value, |
| __ll_mul<R1::den, R2::num>::value>::value, |
| __ll_mul<R1::den, R2::den>::value> type; |
| }; |
| |
| template <class R1, class R2> |
| struct ratio_subtract |
| { |
| typedef ratio<__ll_sub<__ll_mul<R1::num, R2::den>::value, |
| __ll_mul<R1::den, R2::num>::value>::value, |
| __ll_mul<R1::den, R2::den>::value> type; |
| }; |
| |
| template <class R1, class R2> |
| struct ratio_multiply |
| { |
| typedef ratio<__ll_mul<R1::num, R2::num>::value, __ll_mul<R1::den, R2::den>::value> type; |
| }; |
| |
| template <class R1, class R2> |
| struct ratio_divide |
| { |
| typedef ratio<__ll_mul<R1::num, R2::den>::value, __ll_mul<R1::den, R2::num>::value> type; |
| }; |
| |
| <font color="#c80000">// ratio_equal</font> |
| |
| template <class R1, class R2> |
| struct ratio_equal |
| : public tmp::integral_constant<bool, R1::num == R2::num && R1::den == R2::den> {}; |
| |
| template <class R1, class R2> |
| struct ratio_not_equal |
| : public tmp::integral_constant<bool, !ratio_equal<R1, R2>::value> {}; |
| |
| <font color="#c80000">// ratio_less</font> |
| |
| <font color="#c80000">// Protect against overflow, and still get the right answer as much as possible.</font> |
| <font color="#c80000">// This just demonstrates for fun how far you can push things without hitting</font> |
| <font color="#c80000">// overflow. The obvious and simple implementation is conforming.</font> |
| |
| template <class R1, class R2, bool ok1, bool ok2> |
| struct __ratio_less3 <font color="#c80000">// true, true and false, false</font> |
| { |
| static const bool value = __ll_mul<R1::num, R2::den>::value < __ll_mul<R2::num, R1::den>::value; |
| }; |
| |
| template <class R1, class R2> |
| struct __ratio_less3<R1, R2, true, false> |
| { |
| static const bool value = true; |
| }; |
| |
| template <class R1, class R2> |
| struct __ratio_less3<R1, R2, false, true> |
| { |
| static const bool value = false; |
| }; |
| |
| template <class R1, class R2, bool = R1::num < R1::den == R2::num < R2::den> |
| struct __ratio_less2 <font color="#c80000">// N1 < D1 == N2 < D2</font> |
| { |
| static const intmax_t max = -((1LL << (sizeof(intmax_t) * CHAR_BIT - 1)) + 1); |
| static const bool ok1 = R1::num <= max / R2::den; |
| static const bool ok2 = R2::num <= max / R1::den; |
| static const bool value = __ratio_less3<R1, R2, ok1, ok2>::value; |
| }; |
| |
| template <class R1, class R2> |
| struct __ratio_less2<R1, R2, false> <font color="#c80000">// N1 < D1 != N2 < D2</font> |
| { |
| static const bool value = R1::num < R1::den; |
| }; |
| |
| template <class R1, class R2, bool = R1::num < R1::den == R2::num < R2::den> |
| struct __ratio_less1 <font color="#c80000">// N1 < D1 == N2 < D2</font> |
| { |
| static const bool value = __ratio_less2<ratio<R1::num, R2::num>, ratio<R1::den, R2::den> >::value; |
| }; |
| |
| template <class R1, class R2> |
| struct __ratio_less1<R1, R2, false> <font color="#c80000">// N1 < D1 != N2 < D2</font> |
| { |
| static const bool value = R1::num < R1::den; |
| }; |
| |
| template <class R1, class R2, intmax_t S1 = __static_sign<R1::num>::value, |
| intmax_t S2 = __static_sign<R2::num>::value> |
| struct __ratio_less |
| { |
| static const bool value = S1 < S2; |
| }; |
| |
| template <class R1, class R2> |
| struct __ratio_less<R1, R2, 1LL, 1LL> |
| { |
| static const bool value = __ratio_less1<R1, R2>::value; |
| }; |
| |
| template <class R1, class R2> |
| struct __ratio_less<R1, R2, -1LL, -1LL> |
| { |
| static const bool value = __ratio_less1<ratio<-R2::num, R2::den>, ratio<-R1::num, R1::den> >::value; |
| }; |
| |
| template <class R1, class R2> |
| struct ratio_less |
| : public tmp::integral_constant<bool, __ratio_less<R1, R2>::value> {}; |
| |
| template <class R1, class R2> |
| struct ratio_less_equal |
| : public tmp::integral_constant<bool, !ratio_less<R2, R1>::value> {}; |
| |
| template <class R1, class R2> |
| struct ratio_greater |
| : public tmp::integral_constant<bool, ratio_less<R2, R1>::value> {}; |
| |
| template <class R1, class R2> |
| struct ratio_greater_equal |
| : public tmp::integral_constant<bool, !ratio_less<R1, R2>::value> {}; |
| |
| template <class R1, class R2> |
| struct __ratio_gcd |
| { |
| typedef ratio<__static_gcd<R1::num, R2::num>::value, |
| __static_lcm<R1::den, R2::den>::value> type; |
| }; |
| |
| <font color="#c80000">//////////////////////////////////////////////////////////</font> |
| <font color="#c80000">////////////////////// duration //////////////////////////</font> |
| <font color="#c80000">//////////////////////////////////////////////////////////</font> |
| |
| namespace datetime |
| { |
| |
| template <class RepType, class Period = ratio<1> > class duration; |
| |
| template <class T> struct ___is_duration : tmp::false_type {}; |
| template <class Rep, class Period> struct ___is_duration<duration<Rep, Period> > : tmp::true_type {}; |
| template <class T> struct __is_duration : ___is_duration<typename tmp::remove_cv<T>::type> {}; |
| |
| <font color="#c80000">// duration_cast</font> |
| |
| <font color="#c80000">// duration_cast is the heart of this whole prototype. It can convert any</font> |
| <font color="#c80000">// duration to any other. It is also (implicitly) used in converting</font> |
| <font color="#c80000">// time_points. The conversion is always exact if possible. And it is</font> |
| <font color="#c80000">// always as efficient as hand written code. If different representations</font> |
| <font color="#c80000">// are involved, care is taken to never require implicit conversions.</font> |
| <font color="#c80000">// Instead static_cast is used explicitly for every required conversion.</font> |
| <font color="#c80000">// If there are a mixture of integral and floating point representations,</font> |
| <font color="#c80000">// the use of common_type ensures that the most logical "intermediate"</font> |
| <font color="#c80000">// representation is used.</font> |
| template <class FromDuration, class ToDuration, |
| class Period = typename ratio_divide<typename FromDuration::period, typename ToDuration::period>::type, |
| bool = Period::num == 1, |
| bool = Period::den == 1> |
| struct __duration_cast; |
| |
| <font color="#c80000">// When the two periods are the same, all that is left to do is static_cast from</font> |
| <font color="#c80000">// the source representation to the target representation (which may be a no-op).</font> |
| <font color="#c80000">// This conversion is always exact as long as the static_cast from the source</font> |
| <font color="#c80000">// representation to the destination representation is exact.</font> |
| template <class FromDuration, class ToDuration, class Period> |
| struct __duration_cast<FromDuration, ToDuration, Period, true, true> |
| { |
| ToDuration operator()(const FromDuration& fd) const |
| { |
| return ToDuration(static_cast<typename ToDuration::rep>(fd.count())); |
| } |
| }; |
| |
| <font color="#c80000">// When the numerator of FromPeriod / ToPeriod is 1, then all we need to do is</font> |
| <font color="#c80000">// divide by the denominator of FromPeriod / ToPeriod. The common_type of</font> |
| <font color="#c80000">// the two representations is used for the intermediate computation before</font> |
| <font color="#c80000">// static_cast'ing to the destination.</font> |
| <font color="#c80000">// This conversion is generally not exact because of the division (but could be</font> |
| <font color="#c80000">// if you get lucky on the run time value of fd.count()).</font> |
| template <class FromDuration, class ToDuration, class Period> |
| struct __duration_cast<FromDuration, ToDuration, Period, true, false> |
| { |
| ToDuration operator()(const FromDuration& fd) const |
| { |
| #if VARIADIC_COMMON_TYPE == 0 |
| typedef typename common_type< |
| typename common_type<typename ToDuration::rep, typename FromDuration::rep>::type, |
| intmax_t>::type C; |
| #else |
| typedef typename common_type<typename ToDuration::rep, typename FromDuration::rep, intmax_t>::type C; |
| #endif |
| return ToDuration(static_cast<typename ToDuration::rep>( |
| static_cast<C>(fd.count()) / static_cast<C>(Period::den))); |
| } |
| }; |
| |
| <font color="#c80000">// When the denomenator of FromPeriod / ToPeriod is 1, then all we need to do is</font> |
| <font color="#c80000">// multiply by the numerator of FromPeriod / ToPeriod. The common_type of</font> |
| <font color="#c80000">// the two representations is used for the intermediate computation before</font> |
| <font color="#c80000">// static_cast'ing to the destination.</font> |
| <font color="#c80000">// This conversion is always exact as long as the static_cast's involved are exact.</font> |
| template <class FromDuration, class ToDuration, class Period> |
| struct __duration_cast<FromDuration, ToDuration, Period, false, true> |
| { |
| ToDuration operator()(const FromDuration& fd) const |
| { |
| #if VARIADIC_COMMON_TYPE == 0 |
| typedef typename common_type< |
| typename common_type<typename ToDuration::rep, typename FromDuration::rep>::type, |
| intmax_t>::type C; |
| #else |
| typedef typename common_type<typename ToDuration::rep, typename FromDuration::rep, intmax_t>::type C; |
| #endif |
| return ToDuration(static_cast<typename ToDuration::rep>( |
| static_cast<C>(fd.count()) * static_cast<C>(Period::num))); |
| } |
| }; |
| |
| <font color="#c80000">// When neither the numerator or denominator of FromPeriod / ToPeriod is 1, then we need to</font> |
| <font color="#c80000">// multiply by the numerator and divide by the denominator of FromPeriod / ToPeriod. The</font> |
| <font color="#c80000">// common_type of the two representations is used for the intermediate computation before</font> |
| <font color="#c80000">// static_cast'ing to the destination.</font> |
| <font color="#c80000">// This conversion is generally not exact because of the division (but could be</font> |
| <font color="#c80000">// if you get lucky on the run time value of fd.count()).</font> |
| template <class FromDuration, class ToDuration, class Period> |
| struct __duration_cast<FromDuration, ToDuration, Period, false, false> |
| { |
| ToDuration operator()(const FromDuration& fd) const |
| { |
| #if VARIADIC_COMMON_TYPE == 0 |
| typedef typename common_type< |
| typename common_type<typename ToDuration::rep, typename FromDuration::rep>::type, |
| intmax_t>::type C; |
| #else |
| typedef typename common_type<typename ToDuration::rep, typename FromDuration::rep, intmax_t>::type C; |
| #endif |
| return ToDuration(static_cast<typename ToDuration::rep>( |
| static_cast<C>(fd.count()) * static_cast<C>(Period::num) / static_cast<C>(Period::den))); |
| } |
| }; |
| |
| <font color="#c80000">// Compile-time select the most efficient algorithm for the conversion...</font> |
| template <class ToDuration, class Rep, class Period> |
| inline |
| typename tmp::enable_if |
| < |
| __is_duration<ToDuration>::value, |
| ToDuration |
| >::type |
| duration_cast(const duration<Rep, Period>& fd) |
| { |
| return __duration_cast<duration<Rep, Period>, ToDuration>()(fd); |
| } |
| |
| <font color="#c80000">// Support bidirectional (non-exact) conversions for floating point rep types</font> |
| <font color="#c80000">// (or user defined rep types which specialize treat_as_floating_point).</font> |
| template <class Rep> struct treat_as_floating_point : tmp::is_floating_point<Rep> {}; |
| |
| template <class Rep> |
| struct duration_values |
| { |
| static Rep __min_imp(tmp::false_type) {return -max();} |
| static Rep __min_imp(tmp::true_type) {return zero();} |
| public: |
| static Rep zero() {return Rep(0);} |
| static Rep max() {return numeric_limits<Rep>::max();} |
| static Rep min() {return __min_imp(tmp::is_unsigned<Rep>());} |
| }; |
| |
| <font color="#c80000">// duration</font> |
| |
| template <class Rep, class Period> |
| class duration |
| { |
| static char test0[!__is_duration<Rep>::value]; |
| <font color="#c80000">// static_assert(!__is_duration<Rep>::value, "A duration representation can not be a duration");</font> |
| static char test1[__is_ratio<Period>::value]; |
| <font color="#c80000">// static_assert(__is_ratio<Period>::value, "Second template parameter of duration must be a std::ratio");</font> |
| static char test2[Period::num > 0]; |
| <font color="#c80000">// static_assert(Period::num > 0, "duration period must be positive");</font> |
| public: |
| typedef Rep rep; |
| typedef Period period; |
| private: |
| rep rep_; |
| public: |
| |
| duration() {} <font color="#c80000">// = default;</font> |
| template <class Rep2> |
| explicit duration(const Rep2& r, |
| typename tmp::enable_if |
| < |
| tmp::is_convertible<Rep2, rep>::value && |
| (treat_as_floating_point<rep>::value || |
| !treat_as_floating_point<rep>::value && !treat_as_floating_point<Rep2>::value) |
| >::type* = 0) |
| : rep_(r) {} |
| |
| <font color="#c80000">// conversions</font> |
| template <class Rep2, class Period2> |
| duration(const duration<Rep2, Period2>& d, |
| typename tmp::enable_if |
| < |
| treat_as_floating_point<rep>::value || |
| (ratio_divide<Period2, period>::type::den == 1 && !treat_as_floating_point<Rep2>::value) |
| >::type* = 0) |
| : rep_(duration_cast<duration>(d).count()) {} |
| |
| <font color="#c80000">// observer</font> |
| |
| rep count() const {return rep_;} |
| |
| <font color="#c80000">// arithmetic</font> |
| |
| duration operator+() const {return *this;} |
| duration operator-() const {return duration(-rep_);} |
| 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) {rep_ += d.count(); return *this;} |
| duration& operator-=(const duration& d) {rep_ -= d.count(); return *this;} |
| |
| duration& operator*=(const rep& rhs) {rep_ *= rhs; return *this;} |
| duration& operator/=(const rep& rhs) {rep_ /= rhs; return *this;} |
| |
| <font color="#c80000">// special values</font> |
| |
| static duration zero() {return duration(duration_values<rep>::zero());} |
| static duration min() {return duration(duration_values<rep>::min());} |
| static duration max() {return duration(duration_values<rep>::max());} |
| }; |
| |
| typedef duration<long long, nano> nanoseconds; |
| typedef duration<long long, micro> microseconds; |
| typedef duration<long long, milli> milliseconds; |
| typedef duration<long long > seconds; |
| typedef duration< long, ratio< 60> > minutes; |
| typedef duration< long, ratio<3600> > hours; |
| |
| } <font color="#c80000">// datetime</font> |
| |
| template <class Rep1, class Period1, class Rep2, class Period2> |
| struct common_type<datetime::duration<Rep1, Period1>, datetime::duration<Rep2, Period2> > |
| { |
| typedef datetime::duration<typename common_type<Rep1, Rep2>::type, |
| typename __ratio_gcd<Period1, Period2>::type> type; |
| }; |
| |
| namespace datetime { |
| |
| <font color="#c80000">// Duration ==</font> |
| |
| template <class LhsDuration, class RhsDuration> |
| struct __duration_eq |
| { |
| bool operator()(const LhsDuration& lhs, const RhsDuration& rhs) |
| { |
| typedef typename common_type<LhsDuration, RhsDuration>::type CD; |
| return CD(lhs).count() == CD(rhs).count(); |
| } |
| }; |
| |
| template <class LhsDuration> |
| struct __duration_eq<LhsDuration, LhsDuration> |
| { |
| bool operator()(const LhsDuration& lhs, const LhsDuration& rhs) |
| {return lhs.count() == rhs.count();} |
| }; |
| |
| template <class Rep1, class Period1, class Rep2, class Period2> |
| inline |
| bool |
| operator==(const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs) |
| { |
| return __duration_eq<duration<Rep1, Period1>, duration<Rep2, Period2> >()(lhs, rhs); |
| } |
| |
| <font color="#c80000">// Duration !=</font> |
| |
| template <class Rep1, class Period1, class Rep2, class Period2> |
| inline |
| bool |
| operator!=(const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs) |
| { |
| return !(lhs == rhs); |
| } |
| |
| <font color="#c80000">// Duration <</font> |
| |
| template <class LhsDuration, class RhsDuration> |
| struct __duration_lt |
| { |
| bool operator()(const LhsDuration& lhs, const RhsDuration& rhs) |
| { |
| typedef typename common_type<LhsDuration, RhsDuration>::type CD; |
| return CD(lhs).count() < CD(rhs).count(); |
| } |
| }; |
| |
| template <class LhsDuration> |
| struct __duration_lt<LhsDuration, LhsDuration> |
| { |
| bool operator()(const LhsDuration& lhs, const LhsDuration& rhs) |
| {return lhs.count() < rhs.count();} |
| }; |
| |
| template <class Rep1, class Period1, class Rep2, class Period2> |
| inline |
| bool |
| operator< (const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs) |
| { |
| return __duration_lt<duration<Rep1, Period1>, duration<Rep2, Period2> >()(lhs, rhs); |
| } |
| |
| <font color="#c80000">// Duration ></font> |
| |
| template <class Rep1, class Period1, class Rep2, class Period2> |
| inline |
| bool |
| operator> (const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs) |
| { |
| return rhs < lhs; |
| } |
| |
| <font color="#c80000">// Duration <=</font> |
| |
| template <class Rep1, class Period1, class Rep2, class Period2> |
| inline |
| bool |
| operator<=(const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs) |
| { |
| return !(rhs < lhs); |
| } |
| |
| <font color="#c80000">// Duration >=</font> |
| |
| template <class Rep1, class Period1, class Rep2, class Period2> |
| inline |
| bool |
| operator>=(const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs) |
| { |
| return !(lhs < rhs); |
| } |
| |
| <font color="#c80000">// Duration +</font> |
| |
| template <class Rep1, class Period1, class Rep2, class Period2> |
| inline |
| typename common_type<duration<Rep1, Period1>, duration<Rep2, Period2> >::type |
| operator+(const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs) |
| { |
| typename common_type<duration<Rep1, Period1>, duration<Rep2, Period2> >::type result = lhs; |
| result += rhs; |
| return result; |
| } |
| |
| <font color="#c80000">// Duration -</font> |
| |
| template <class Rep1, class Period1, class Rep2, class Period2> |
| inline |
| typename common_type<duration<Rep1, Period1>, duration<Rep2, Period2> >::type |
| operator-(const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs) |
| { |
| typename common_type<duration<Rep1, Period1>, duration<Rep2, Period2> >::type result = lhs; |
| result -= rhs; |
| return result; |
| } |
| |
| <font color="#c80000">// Duration *</font> |
| |
| template <class Rep1, class Period, class Rep2> |
| inline |
| typename tmp::enable_if |
| < |
| tmp::is_convertible<Rep1, typename common_type<Rep1, Rep2>::type>::value && |
| tmp::is_convertible<Rep2, typename common_type<Rep1, Rep2>::type>::value, |
| duration<typename common_type<Rep1, Rep2>::type, Period> |
| >::type |
| operator*(const duration<Rep1, Period>& d, const Rep2& s) |
| { |
| typedef typename common_type<Rep1, Rep2>::type CR; |
| duration<CR, Period> r = d; |
| r *= static_cast<CR>(s); |
| return r; |
| } |
| |
| template <class Rep1, class Period, class Rep2> |
| inline |
| typename tmp::enable_if |
| < |
| tmp::is_convertible<Rep1, typename common_type<Rep1, Rep2>::type>::value && |
| tmp::is_convertible<Rep2, typename common_type<Rep1, Rep2>::type>::value, |
| duration<typename common_type<Rep1, Rep2>::type, Period> |
| >::type |
| operator*(const Rep1& s, const duration<Rep2, Period>& d) |
| { |
| return d * s; |
| } |
| |
| <font color="#c80000">// Duration /</font> |
| |
| template <class Duration, class Rep, bool = __is_duration<Rep>::value> |
| struct __duration_divide_result |
| { |
| }; |
| |
| template <class Duration, class Rep2, |
| bool = tmp::is_convertible<typename Duration::rep, |
| typename common_type<typename Duration::rep, Rep2>::type>::value && |
| tmp::is_convertible<Rep2, |
| typename common_type<typename Duration::rep, Rep2>::type>::value> |
| struct __duration_divide_imp |
| { |
| }; |
| |
| template <class Rep1, class Period, class Rep2> |
| struct __duration_divide_imp<duration<Rep1, Period>, Rep2, true> |
| { |
| typedef duration<typename common_type<Rep1, Rep2>::type, Period> type; |
| }; |
| |
| template <class Rep1, class Period, class Rep2> |
| struct __duration_divide_result<duration<Rep1, Period>, Rep2, false> |
| : __duration_divide_imp<duration<Rep1, Period>, Rep2> |
| { |
| }; |
| |
| template <class Rep1, class Period, class Rep2> |
| inline |
| typename __duration_divide_result<duration<Rep1, Period>, Rep2>::type |
| operator/(const duration<Rep1, Period>& d, const Rep2& s) |
| { |
| typedef typename common_type<Rep1, Rep2>::type CR; |
| duration<CR, Period> r = d; |
| r /= static_cast<CR>(s); |
| return r; |
| } |
| |
| template <class Rep1, class Period1, class Rep2, class Period2> |
| inline |
| typename common_type<Rep1, Rep2>::type |
| operator/(const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs) |
| { |
| typedef typename common_type<duration<Rep1, Period1>, duration<Rep2, Period2> >::type CD; |
| return CD(lhs).count() / CD(rhs).count(); |
| } |
| |
| <font color="#c80000">//////////////////////////////////////////////////////////</font> |
| <font color="#c80000">///////////////////// time_point /////////////////////////</font> |
| <font color="#c80000">//////////////////////////////////////////////////////////</font> |
| |
| template <class Clock, class Duration = typename Clock::duration> |
| class time_point |
| { |
| static char test1[__is_duration<Duration>::value]; |
| <font color="#c80000">// static_assert(__is_duration<Duration>::value,</font> |
| <font color="#c80000">// "Second template parameter of time_point must be a std::datetime::duration");</font> |
| public: |
| typedef Clock clock; |
| typedef Duration duration; |
| typedef typename duration::rep rep; |
| typedef typename duration::period period; |
| private: |
| duration d_; |
| |
| public: |
| time_point() : d_(duration::zero()) {} |
| explicit time_point(const duration& d) : d_(d) {} |
| |
| <font color="#c80000">// conversions</font> |
| template <class Duration2> |
| time_point(const time_point<clock, Duration2>& t, |
| typename tmp::enable_if |
| < |
| tmp::is_convertible<Duration2, duration>::value |
| >::type* = 0) |
| : d_(t.time_since_epoch()) {} |
| |
| <font color="#c80000">// observer</font> |
| |
| duration time_since_epoch() const {return d_;} |
| |
| <font color="#c80000">// arithmetic</font> |
| |
| time_point& operator+=(const duration& d) {d_ += d; return *this;} |
| time_point& operator-=(const duration& d) {d_ -= d; return *this;} |
| |
| <font color="#c80000">// special values</font> |
| |
| static time_point min() {return time_point(duration::min());} |
| static time_point max() {return time_point(duration::max());} |
| }; |
| |
| } <font color="#c80000">// datetime</font> |
| |
| template <class Clock, class Duration1, class Duration2> |
| struct common_type<datetime::time_point<Clock, Duration1>, datetime::time_point<Clock, Duration2> > |
| { |
| typedef datetime::time_point<Clock, typename common_type<Duration1, Duration2>::type> type; |
| }; |
| |
| namespace datetime { |
| |
| template <class ToDuration, class Clock, class Duration> |
| inline |
| time_point<Clock, ToDuration> |
| time_point_cast(const time_point<Clock, Duration>& t) |
| { |
| return time_point<Clock, ToDuration>(duration_cast<ToDuration>(t.time_since_epoch())); |
| } |
| |
| <font color="#c80000">// time_point ==</font> |
| |
| template <class Clock, class Duration1, class Duration2> |
| inline |
| bool |
| operator==(const time_point<Clock, Duration1>& lhs, const time_point<Clock, Duration2>& rhs) |
| { |
| return lhs.time_since_epoch() == rhs.time_since_epoch(); |
| } |
| |
| <font color="#c80000">// time_point !=</font> |
| |
| template <class Clock, class Duration1, class Duration2> |
| inline |
| bool |
| operator!=(const time_point<Clock, Duration1>& lhs, const time_point<Clock, Duration2>& rhs) |
| { |
| return !(lhs == rhs); |
| } |
| |
| <font color="#c80000">// time_point <</font> |
| |
| template <class Clock, class Duration1, class Duration2> |
| inline |
| bool |
| operator<(const time_point<Clock, Duration1>& lhs, const time_point<Clock, Duration2>& rhs) |
| { |
| return lhs.time_since_epoch() < rhs.time_since_epoch(); |
| } |
| |
| <font color="#c80000">// time_point ></font> |
| |
| template <class Clock, class Duration1, class Duration2> |
| inline |
| bool |
| operator>(const time_point<Clock, Duration1>& lhs, const time_point<Clock, Duration2>& rhs) |
| { |
| return rhs < lhs; |
| } |
| |
| <font color="#c80000">// time_point <=</font> |
| |
| template <class Clock, class Duration1, class Duration2> |
| inline |
| bool |
| operator<=(const time_point<Clock, Duration1>& lhs, const time_point<Clock, Duration2>& rhs) |
| { |
| return !(rhs < lhs); |
| } |
| |
| <font color="#c80000">// time_point >=</font> |
| |
| template <class Clock, class Duration1, class Duration2> |
| inline |
| bool |
| operator>=(const time_point<Clock, Duration1>& lhs, const time_point<Clock, Duration2>& rhs) |
| { |
| return !(lhs < rhs); |
| } |
| |
| <font color="#c80000">// time_point operator+(time_point x, duration y);</font> |
| |
| template <class Clock, class Duration1, class Rep2, class Period2> |
| inline |
| time_point<Clock, typename common_type<Duration1, duration<Rep2, Period2> >::type> |
| operator+(const time_point<Clock, Duration1>& lhs, const duration<Rep2, Period2>& rhs) |
| { |
| typedef time_point<Clock, typename common_type<Duration1, duration<Rep2, Period2> >::type> TimeResult; |
| TimeResult r(lhs); |
| r += rhs; |
| return r; |
| } |
| |
| <font color="#c80000">// time_point operator+(duration x, time_point y);</font> |
| |
| template <class Rep1, class Period1, class Clock, class Duration2> |
| inline |
| time_point<Clock, typename common_type<duration<Rep1, Period1>, Duration2>::type> |
| operator+(const duration<Rep1, Period1>& lhs, const time_point<Clock, Duration2>& rhs) |
| { |
| return rhs + lhs; |
| } |
| |
| <font color="#c80000">// time_point operator-(time_point x, duration y);</font> |
| |
| template <class Clock, class Duration1, class Rep2, class Period2> |
| inline |
| time_point<Clock, typename common_type<Duration1, duration<Rep2, Period2> >::type> |
| operator-(const time_point<Clock, Duration1>& lhs, const duration<Rep2, Period2>& rhs) |
| { |
| return lhs + (-rhs); |
| } |
| |
| <font color="#c80000">// duration operator-(time_point x, time_point y);</font> |
| |
| template <class Clock, class Duration1, class Duration2> |
| inline |
| typename common_type<Duration1, Duration2>::type |
| operator-(const time_point<Clock, Duration1>& lhs, const time_point<Clock, Duration2>& rhs) |
| { |
| return lhs.time_since_epoch() - rhs.time_since_epoch(); |
| } |
| |
| <font color="#c80000">//////////////////////////////////////////////////////////</font> |
| <font color="#c80000">/////////////////////// clocks ///////////////////////////</font> |
| <font color="#c80000">//////////////////////////////////////////////////////////</font> |
| |
| <font color="#c80000">// If you're porting, clocks are the system-specific (non-portable) part.</font> |
| <font color="#c80000">// You'll need to know how to get the current time and implement that under now().</font> |
| <font color="#c80000">// You'll need to know what units (tick period) and representation makes the most</font> |
| <font color="#c80000">// sense for your clock and set those accordingly.</font> |
| <font color="#c80000">// If you know how to map this clock to time_t (perhaps your clock is std::time, which</font> |
| <font color="#c80000">// makes that trivial), then you can fill out system_clock's to_time_t() and from_time_t().</font> |
| |
| class system_clock |
| { |
| public: |
| typedef microseconds duration; |
| typedef duration::rep rep; |
| typedef duration::period period; |
| typedef datetime::time_point<system_clock> time_point; |
| static const bool is_monotonic = false; |
| |
| static time_point now(); |
| static time_t to_time_t (const time_point& t); |
| static time_point from_time_t(time_t t); |
| }; |
| |
| class monotonic_clock |
| { |
| public: |
| typedef nanoseconds duration; |
| typedef duration::rep rep; |
| typedef duration::period period; |
| typedef datetime::time_point<monotonic_clock> time_point; |
| static const bool is_monotonic = true; |
| |
| static time_point now(); |
| }; |
| |
| typedef monotonic_clock high_resolution_clock; |
| |
| } <font color="#c80000">// datetime</font> |
| } <font color="#c80000">// std</font> |
| |
| <font color="#c80000">// clocks.cpp</font> |
| |
| #include <sys/time.h> <font color="#c80000">//for gettimeofday and timeval</font> |
| #include <mach/mach_time.h> <font color="#c80000">// mach_absolute_time, mach_timebase_info_data_t</font> |
| |
| namespace std { |
| namespace datetime { |
| |
| <font color="#c80000">// system_clock</font> |
| |
| <font color="#c80000">// gettimeofday is the most precise "system time" available on this platform.</font> |
| <font color="#c80000">// It returns the number of microseconds since New Years 1970 in a struct called timeval</font> |
| <font color="#c80000">// which has a field for seconds and a field for microseconds.</font> |
| <font color="#c80000">// Fill in the timeval and then convert that to the time_point</font> |
| system_clock::time_point |
| system_clock::now() |
| { |
| timeval tv; |
| gettimeofday(&tv, 0); |
| return time_point(seconds(tv.tv_sec) + microseconds(tv.tv_usec)); |
| } |
| |
| <font color="#c80000">// Take advantage of the fact that on this platform time_t is nothing but</font> |
| <font color="#c80000">// an integral count of seconds since New Years 1970 (same epoch as timeval).</font> |
| <font color="#c80000">// Just get the duration out of the time_point and truncate it to seconds.</font> |
| time_t |
| system_clock::to_time_t(const time_point& t) |
| { |
| return time_t(duration_cast<seconds>(t.time_since_epoch()).count()); |
| } |
| |
| <font color="#c80000">// Just turn the time_t into a count of seconds and construct a time_point with it.</font> |
| system_clock::time_point |
| system_clock::from_time_t(time_t t) |
| { |
| return system_clock::time_point(seconds(t)); |
| } |
| |
| <font color="#c80000">// monotonic_clock</font> |
| |
| <font color="#c80000">// Note, in this implementation monotonic_clock and high_resolution_clock</font> |
| <font color="#c80000">// are the same clock. They are both based on mach_absolute_time().</font> |
| <font color="#c80000">// mach_absolute_time() * MachInfo.numer / MachInfo.denom is the number of</font> |
| <font color="#c80000">// nanoseconds since the computer booted up. MachInfo.numer and MachInfo.denom</font> |
| <font color="#c80000">// are run time constants supplied by the OS. This clock has no relationship</font> |
| <font color="#c80000">// to the Gregorian calendar. It's main use is as a high resolution timer.</font> |
| |
| <font color="#c80000">// MachInfo.numer / MachInfo.denom is often 1 on the latest equipment. Specialize</font> |
| <font color="#c80000">// for that case as an optimization.</font> |
| static |
| monotonic_clock::rep |
| monotonic_simplified() |
| { |
| return mach_absolute_time(); |
| } |
| |
| static |
| double |
| compute_monotonic_factor() |
| { |
| mach_timebase_info_data_t MachInfo; |
| mach_timebase_info(&MachInfo); |
| return static_cast<double>(MachInfo.numer) / MachInfo.denom; |
| } |
| |
| static |
| monotonic_clock::rep |
| monotonic_full() |
| { |
| static const double factor = compute_monotonic_factor(); |
| return static_cast<monotonic_clock::rep>(mach_absolute_time() * factor); |
| } |
| |
| typedef monotonic_clock::rep (*FP)(); |
| |
| static |
| FP |
| init_monotonic_clock() |
| { |
| mach_timebase_info_data_t MachInfo; |
| mach_timebase_info(&MachInfo); |
| if (MachInfo.numer == MachInfo.denom) |
| return &monotonic_simplified; |
| return &monotonic_full; |
| } |
| |
| monotonic_clock::time_point |
| monotonic_clock::now() |
| { |
| static FP fp = init_monotonic_clock(); |
| return time_point(duration(fp())); |
| } |
| |
| <font color="#c80000">// clocks.cpp end</font> |
| |
| } } <font color="#c80000">// std::datetime</font> |
| |
| <font color="#c80000">//////////////////////////////////////////////////////////</font> |
| <font color="#c80000">///////////// simulated thread interface /////////////////</font> |
| <font color="#c80000">//////////////////////////////////////////////////////////</font> |
| |
| #include <iostream> |
| |
| namespace std { |
| |
| void __print_time(datetime::system_clock::time_point t) |
| { |
| using namespace datetime; |
| time_t c_time = system_clock::to_time_t(t); |
| std::tm* tmptr = std::localtime(&c_time); |
| system_clock::duration d = t.time_since_epoch(); |
| std::cout << tmptr->tm_hour << ':' << tmptr->tm_min << ':' << tmptr->tm_sec |
| << '.' << (d - duration_cast<seconds>(d)).count(); |
| } |
| |
| namespace this_thread { |
| |
| template <class Rep, class Period> |
| void sleep_for(const datetime::duration<Rep, Period>& d) |
| { |
| datetime::microseconds t = datetime::duration_cast<datetime::microseconds>(d); |
| if (t < d) |
| ++t; |
| if (t > datetime::microseconds(0)) |
| std::cout << "sleep_for " << t.count() << " microseconds\n"; |
| } |
| |
| template <class Clock, class Duration> |
| void sleep_until(const datetime::time_point<Clock, Duration>& t) |
| { |
| using namespace datetime; |
| typedef time_point<Clock, Duration> Time; |
| typedef system_clock::time_point SysTime; |
| if (t > Clock::now()) |
| { |
| typedef typename common_type<typename Time::duration, typename SysTime::duration>::type D; |
| <font color="#c80000">/* auto */</font> D d = t - Clock::now(); |
| microseconds us = duration_cast<microseconds>(d); |
| if (us < d) |
| ++us; |
| SysTime st = system_clock::now() + us; |
| std::cout << "sleep_until "; |
| __print_time(st); |
| std::cout << " which is " << (st - system_clock::now()).count() << " microseconds away\n"; |
| } |
| } |
| |
| } <font color="#c80000">// this_thread</font> |
| |
| struct mutex {}; |
| |
| struct timed_mutex |
| { |
| bool try_lock() {std::cout << "timed_mutex::try_lock()\n";} |
| |
| template <class Rep, class Period> |
| bool try_lock_for(const datetime::duration<Rep, Period>& d) |
| { |
| datetime::microseconds t = datetime::duration_cast<datetime::microseconds>(d); |
| if (t <= datetime::microseconds(0)) |
| return try_lock(); |
| std::cout << "try_lock_for " << t.count() << " microseconds\n"; |
| return true; |
| } |
| |
| template <class Clock, class Duration> |
| bool try_lock_until(const datetime::time_point<Clock, Duration>& t) |
| { |
| using namespace datetime; |
| typedef time_point<Clock, Duration> Time; |
| typedef system_clock::time_point SysTime; |
| if (t <= Clock::now()) |
| return try_lock(); |
| typedef typename common_type<typename Time::duration, typename Clock::duration>::type D; |
| <font color="#c80000">/* auto */</font> D d = t - Clock::now(); |
| microseconds us = duration_cast<microseconds>(d); |
| SysTime st = system_clock::now() + us; |
| std::cout << "try_lock_until "; |
| __print_time(st); |
| std::cout << " which is " << (st - system_clock::now()).count() << " microseconds away\n"; |
| } |
| }; |
| |
| struct condition_variable |
| { |
| template <class Rep, class Period> |
| bool wait_for(mutex&, const datetime::duration<Rep, Period>& d) |
| { |
| datetime::microseconds t = datetime::duration_cast<datetime::microseconds>(d); |
| std::cout << "wait_for " << t.count() << " microseconds\n"; |
| return true; |
| } |
| |
| template <class Clock, class Duration> |
| bool wait_until(mutex&, const datetime::time_point<Clock, Duration>& t) |
| { |
| using namespace datetime; |
| typedef time_point<Clock, Duration> Time; |
| typedef system_clock::time_point SysTime; |
| if (t <= Clock::now()) |
| return false; |
| typedef typename common_type<typename Time::duration, typename Clock::duration>::type D; |
| <font color="#c80000">/* auto */</font> D d = t - Clock::now(); |
| microseconds us = duration_cast<microseconds>(d); |
| SysTime st = system_clock::now() + us; |
| std::cout << "wait_until "; |
| __print_time(st); |
| std::cout << " which is " << (st - system_clock::now()).count() << " microseconds away\n"; |
| } |
| }; |
| |
| } <font color="#c80000">// std</font> |
| |
| <font color="#c80000">//////////////////////////////////////////////////////////</font> |
| <font color="#c80000">/////////////////// End of implemetation ////////////////</font> |
| <font color="#c80000">//////////////////////////////////////////////////////////</font> |
| |
| <font color="#c80000">//////////////////////////////////////////////////////////</font> |
| <font color="#c80000">//////////// Simple sleep and wait examples //////////////</font> |
| <font color="#c80000">//////////////////////////////////////////////////////////</font> |
| |
| std::mutex m; |
| std::timed_mutex mut; |
| std::condition_variable cv; |
| |
| void basic_examples() |
| { |
| std::cout << "Running basic examples\n"; |
| using namespace std; |
| using namespace std::datetime; |
| system_clock::time_point time_limit = system_clock::now() + seconds(4) + milliseconds(500); |
| this_thread::sleep_for(seconds(3)); |
| this_thread::sleep_for(nanoseconds(300)); |
| this_thread::sleep_until(time_limit); |
| <font color="#c80000">// this_thread::sleep_for(time_limit); // desired compile-time error</font> |
| <font color="#c80000">// this_thread::sleep_until(seconds(3)); // desired compile-time error</font> |
| mut.try_lock_for(milliseconds(30)); |
| mut.try_lock_until(time_limit); |
| <font color="#c80000">// mut.try_lock_for(time_limit); // desired compile-time error</font> |
| <font color="#c80000">// mut.try_lock_until(milliseconds(30)); // desired compile-time error</font> |
| cv.wait_for(m, minutes(1)); <font color="#c80000">// real code would put this in a loop</font> |
| cv.wait_until(m, time_limit); <font color="#c80000">// real code would put this in a loop</font> |
| <font color="#c80000">// For those who prefer floating point</font> |
| this_thread::sleep_for(duration<double>(0.25)); |
| this_thread::sleep_until(system_clock::now() + duration<double>(1.5)); |
| } |
| |
| <font color="#c80000">//////////////////////////////////////////////////////////</font> |
| <font color="#c80000">//////////////////// User1 Example ///////////////////////</font> |
| <font color="#c80000">//////////////////////////////////////////////////////////</font> |
| |
| namespace User1 |
| { |
| <font color="#c80000">// Example type-safe "physics" code interoperating with std::datetime::duration types</font> |
| <font color="#c80000">// and taking advantage of the std::ratio infrastructure and design philosophy.</font> |
| |
| <font color="#c80000">// length - mimics std::datetime::duration except restricts representation to double.</font> |
| <font color="#c80000">// Uses std::ratio facilities for length units conversions.</font> |
| |
| template <class Ratio> |
| class length |
| { |
| public: |
| typedef Ratio ratio; |
| private: |
| double len_; |
| public: |
| |
| length() : len_(1) {} |
| length(const double& len) : len_(len) {} |
| |
| <font color="#c80000">// conversions</font> |
| template <class R> |
| length(const length<R>& d) |
| : len_(d.count() * std::ratio_divide<Ratio, R>::type::den / |
| std::ratio_divide<Ratio, R>::type::num) {} |
| |
| <font color="#c80000">// observer</font> |
| |
| double count() const {return len_;} |
| |
| <font color="#c80000">// arithmetic</font> |
| |
| length& operator+=(const length& d) {len_ += d.count(); return *this;} |
| length& operator-=(const length& d) {len_ -= d.count(); return *this;} |
| |
| length operator+() const {return *this;} |
| length operator-() const {return length(-len_);} |
| |
| length& operator*=(double rhs) {len_ *= rhs; return *this;} |
| length& operator/=(double rhs) {len_ /= rhs; return *this;} |
| }; |
| |
| <font color="#c80000">// Sparse sampling of length units</font> |
| typedef length<std::ratio<1> > meter; <font color="#c80000">// set meter as "unity"</font> |
| typedef length<std::centi> centimeter; <font color="#c80000">// 1/100 meter</font> |
| typedef length<std::kilo> kilometer; <font color="#c80000">// 1000 meters</font> |
| typedef length<std::ratio<254, 10000> > inch; <font color="#c80000">// 254/10000 meters</font> |
| <font color="#c80000">// length takes ratio instead of two integral types so that definitions can be made like so:</font> |
| typedef length<std::ratio_multiply<std::ratio<12>, inch::ratio>::type> foot; <font color="#c80000">// 12 inchs</font> |
| typedef length<std::ratio_multiply<std::ratio<5280>, foot::ratio>::type> mile; <font color="#c80000">// 5280 feet</font> |
| |
| <font color="#c80000">// Need a floating point definition of seconds</font> |
| typedef std::datetime::duration<double> seconds; <font color="#c80000">// unity</font> |
| <font color="#c80000">// Demo of (scientific) support for sub-nanosecond resolutions</font> |
| typedef std::datetime::duration<double, std::pico> picosecond; <font color="#c80000">// 10^-12 seconds</font> |
| typedef std::datetime::duration<double, std::femto> femtosecond; <font color="#c80000">// 10^-15 seconds</font> |
| typedef std::datetime::duration<double, std::atto> attosecond; <font color="#c80000">// 10^-18 seconds</font> |
| |
| <font color="#c80000">// A very brief proof-of-concept for SIUnits-like library</font> |
| <font color="#c80000">// Hard-wired to floating point seconds and meters, but accepts other units (shown in testUser1())</font> |
| template <class R1, class R2> |
| class quantity |
| { |
| double q_; |
| public: |
| quantity() : q_(1) {} |
| |
| double get() const {return q_;} |
| void set(double q) {q_ = q;} |
| }; |
| |
| template <> |
| class quantity<std::ratio<1>, std::ratio<0> > |
| { |
| double q_; |
| public: |
| quantity() : q_(1) {} |
| quantity(seconds d) : q_(d.count()) {} <font color="#c80000">// note: only User1::seconds needed here</font> |
| |
| double get() const {return q_;} |
| void set(double q) {q_ = q;} |
| }; |
| |
| template <> |
| class quantity<std::ratio<0>, std::ratio<1> > |
| { |
| double q_; |
| public: |
| quantity() : q_(1) {} |
| quantity(meter d) : q_(d.count()) {} <font color="#c80000">// note: only User1::meter needed here</font> |
| |
| double get() const {return q_;} |
| void set(double q) {q_ = q;} |
| }; |
| |
| template <> |
| class quantity<std::ratio<0>, std::ratio<0> > |
| { |
| double q_; |
| public: |
| quantity() : q_(1) {} |
| quantity(double d) : q_(d) {} |
| |
| double get() const {return q_;} |
| void set(double q) {q_ = q;} |
| }; |
| |
| <font color="#c80000">// Example SI-Units</font> |
| typedef quantity<std::ratio<0>, std::ratio<0> > Scalar; |
| typedef quantity<std::ratio<1>, std::ratio<0> > Time; <font color="#c80000">// second</font> |
| typedef quantity<std::ratio<0>, std::ratio<1> > Distance; <font color="#c80000">// meter</font> |
| typedef quantity<std::ratio<-1>, std::ratio<1> > Speed; <font color="#c80000">// meter/second</font> |
| typedef quantity<std::ratio<-2>, std::ratio<1> > Acceleration; <font color="#c80000">// meter/second^2</font> |
| |
| template <class R1, class R2, class R3, class R4> |
| quantity<typename std::ratio_subtract<R1, R3>::type, typename std::ratio_subtract<R2, R4>::type> |
| operator/(const quantity<R1, R2>& x, const quantity<R3, R4>& y) |
| { |
| typedef quantity<typename std::ratio_subtract<R1, R3>::type, typename std::ratio_subtract<R2, R4>::type> R; |
| R r; |
| r.set(x.get() / y.get()); |
| return r; |
| } |
| |
| template <class R1, class R2, class R3, class R4> |
| quantity<typename std::ratio_add<R1, R3>::type, typename std::ratio_add<R2, R4>::type> |
| operator*(const quantity<R1, R2>& x, const quantity<R3, R4>& y) |
| { |
| typedef quantity<typename std::ratio_add<R1, R3>::type, typename std::ratio_add<R2, R4>::type> R; |
| R r; |
| r.set(x.get() * y.get()); |
| return r; |
| } |
| |
| template <class R1, class R2> |
| quantity<R1, R2> |
| operator+(const quantity<R1, R2>& x, const quantity<R1, R2>& y) |
| { |
| typedef quantity<R1, R2> R; |
| R r; |
| r.set(x.get() + y.get()); |
| return r; |
| } |
| |
| template <class R1, class R2> |
| quantity<R1, R2> |
| operator-(const quantity<R1, R2>& x, const quantity<R1, R2>& y) |
| { |
| typedef quantity<R1, R2> R; |
| R r; |
| r.set(x.get() - y.get()); |
| return r; |
| } |
| |
| <font color="#c80000">// Example type-safe physics function</font> |
| Distance |
| compute_distance(Speed v0, Time t, Acceleration a) |
| { |
| return v0 * t + Scalar(.5) * a * t * t; <font color="#c80000">// if a units mistake is made here it won't compile</font> |
| } |
| |
| } <font color="#c80000">// User1</font> |
| |
| #include <iostream> |
| |
| <font color="#c80000">// Exercise example type-safe physics function and show interoperation</font> |
| <font color="#c80000">// of custom time durations (User1::seconds) and standard time durations (std::hours).</font> |
| <font color="#c80000">// Though input can be arbitrary (but type-safe) units, output is always in SI-units</font> |
| <font color="#c80000">// (a limitation of the simplified Units lib demoed here).</font> |
| void testUser1() |
| { |
| std::cout << "*************\n"; |
| std::cout << "* testUser1 *\n"; |
| std::cout << "*************\n"; |
| User1::Distance d( User1::mile(110) ); |
| User1::Time t( std::datetime::hours(2) ); |
| User1::Speed s = d / t; |
| std::cout << "Speed = " << s.get() << " meters/sec\n"; |
| User1::Acceleration a = User1::Distance( User1::foot(32.2) ) / User1::Time() / User1::Time(); |
| std::cout << "Acceleration = " << a.get() << " meters/sec^2\n"; |
| User1::Distance df = compute_distance(s, User1::Time( User1::seconds(0.5) ), a); |
| std::cout << "Distance = " << df.get() << " meters\n"; |
| std::cout << "There are " << User1::mile::ratio::den << '/' << User1::mile::ratio::num << " miles/meter"; |
| User1::meter mt = 1; |
| User1::mile mi = mt; |
| std::cout << " which is approximately " << mi.count() << '\n'; |
| std::cout << "There are " << User1::mile::ratio::num << '/' << User1::mile::ratio::den << " meters/mile"; |
| mi = 1; |
| mt = mi; |
| std::cout << " which is approximately " << mt.count() << '\n'; |
| User1::attosecond as(1); |
| User1::seconds sec = as; |
| std::cout << "1 attosecond is " << sec.count() << " seconds\n"; |
| std::cout << "sec = as; <font color="#c80000">// compiles\n";</font> |
| sec = User1::seconds(1); |
| as = sec; |
| std::cout << "1 second is " << as.count() << " attoseconds\n"; |
| std::cout << "as = sec; <font color="#c80000">// compiles\n";</font> |
| std::cout << "\n"; |
| } |
| |
| <font color="#c80000">//////////////////////////////////////////////////////////</font> |
| <font color="#c80000">//////////////////// User2 Example ///////////////////////</font> |
| <font color="#c80000">//////////////////////////////////////////////////////////</font> |
| |
| <font color="#c80000">// Demonstrate User2:</font> |
| <font color="#c80000">// A "saturating" signed integral type is developed. This type has +/- infinity and a nan</font> |
| <font color="#c80000">// (like IEEE floating point) but otherwise obeys signed integral arithmetic.</font> |
| <font color="#c80000">// This class is subsequently used as the rep in std::datetime::duration to demonstrate a</font> |
| <font color="#c80000">// duration class that does not silently ignore overflow.</font> |
| #include <ostream> |
| #include <stdexcept> |
| #include <climits> |
| |
| namespace User2 |
| { |
| |
| template <class I> |
| class saturate |
| { |
| public: |
| typedef I int_type; |
| |
| static const int_type nan = int_type(int_type(1) << (sizeof(int_type) * CHAR_BIT - 1)); |
| static const int_type neg_inf = nan + 1; |
| static const int_type pos_inf = -neg_inf; |
| private: |
| int_type i_; |
| |
| <font color="#c80000">// static_assert(std::is_integral<int_type>::value && std::is_signed<int_type>::value,</font> |
| <font color="#c80000">// "saturate only accepts signed integral types");</font> |
| <font color="#c80000">// static_assert(nan == -nan && neg_inf < pos_inf,</font> |
| <font color="#c80000">// "saturate assumes two's complement hardware for signed integrals");</font> |
| |
| public: |
| saturate() : i_(nan) {} |
| explicit saturate(int_type i) : i_(i) {} |
| <font color="#c80000">// explicit</font> |
| operator int_type() const; |
| |
| saturate& operator+=(saturate x); |
| saturate& operator-=(saturate x) {return *this += -x;} |
| saturate& operator*=(saturate x); |
| saturate& operator/=(saturate x); |
| saturate& operator%=(saturate x); |
| |
| saturate operator- () const {return saturate(-i_);} |
| saturate& operator++() {*this += saturate(int_type(1)); return *this;} |
| saturate operator++(int) {saturate tmp(*this); ++(*this); return tmp;} |
| saturate& operator--() {*this -= saturate(int_type(1)); return *this;} |
| saturate operator--(int) {saturate tmp(*this); --(*this); return tmp;} |
| |
| friend saturate operator+(saturate x, saturate y) {return x += y;} |
| friend saturate operator-(saturate x, saturate y) {return x -= y;} |
| friend saturate operator*(saturate x, saturate y) {return x *= y;} |
| friend saturate operator/(saturate x, saturate y) {return x /= y;} |
| friend saturate operator%(saturate x, saturate y) {return x %= y;} |
| |
| friend bool operator==(saturate x, saturate y) |
| { |
| if (x.i_ == nan || y.i_ == nan) |
| return false; |
| return x.i_ == y.i_; |
| } |
| |
| friend bool operator!=(saturate x, saturate y) {return !(x == y);} |
| |
| friend bool operator<(saturate x, saturate y) |
| { |
| if (x.i_ == nan || y.i_ == nan) |
| return false; |
| return x.i_ < y.i_; |
| } |
| |
| friend bool operator<=(saturate x, saturate y) |
| { |
| if (x.i_ == nan || y.i_ == nan) |
| return false; |
| return x.i_ <= y.i_; |
| } |
| |
| friend bool operator>(saturate x, saturate y) |
| { |
| if (x.i_ == nan || y.i_ == nan) |
| return false; |
| return x.i_ > y.i_; |
| } |
| |
| friend bool operator>=(saturate x, saturate y) |
| { |
| if (x.i_ == nan || y.i_ == nan) |
| return false; |
| return x.i_ >= y.i_; |
| } |
| |
| friend std::ostream& operator<<(std::ostream& os, saturate s) |
| { |
| switch (s.i_) |
| { |
| case pos_inf: |
| return os << "inf"; |
| case nan: |
| return os << "nan"; |
| case neg_inf: |
| return os << "-inf"; |
| }; |
| return os << s.i_; |
| } |
| }; |
| |
| template <class I> |
| saturate<I>::operator int_type() const |
| { |
| switch (i_) |
| { |
| case nan: |
| case neg_inf: |
| case pos_inf: |
| throw std::out_of_range("saturate special value can not convert to int_type"); |
| } |
| return i_; |
| } |
| |
| template <class I> |
| saturate<I>& |
| saturate<I>::operator+=(saturate x) |
| { |
| switch (i_) |
| { |
| case pos_inf: |
| switch (x.i_) |
| { |
| case neg_inf: |
| case nan: |
| i_ = nan; |
| } |
| return *this; |
| case nan: |
| return *this; |
| case neg_inf: |
| switch (x.i_) |
| { |
| case pos_inf: |
| case nan: |
| i_ = nan; |
| } |
| return *this; |
| } |
| switch (x.i_) |
| { |
| case pos_inf: |
| case neg_inf: |
| case nan: |
| i_ = x.i_; |
| return *this; |
| } |
| if (x.i_ >= 0) |
| { |
| if (i_ < pos_inf - x.i_) |
| i_ += x.i_; |
| else |
| i_ = pos_inf; |
| return *this; |
| } |
| if (i_ > neg_inf - x.i_) |
| i_ += x.i_; |
| else |
| i_ = neg_inf; |
| return *this; |
| } |
| |
| template <class I> |
| saturate<I>& |
| saturate<I>::operator*=(saturate x) |
| { |
| switch (i_) |
| { |
| case 0: |
| switch (x.i_) |
| { |
| case pos_inf: |
| case neg_inf: |
| case nan: |
| i_ = nan; |
| } |
| return *this; |
| case pos_inf: |
| switch (x.i_) |
| { |
| case nan: |
| case 0: |
| i_ = nan; |
| return *this; |
| } |
| if (x.i_ < 0) |
| i_ = neg_inf; |
| return *this; |
| case nan: |
| return *this; |
| case neg_inf: |
| switch (x.i_) |
| { |
| case nan: |
| case 0: |
| i_ = nan; |
| return *this; |
| } |
| if (x.i_ < 0) |
| i_ = pos_inf; |
| return *this; |
| } |
| switch (x.i_) |
| { |
| case 0: |
| i_ = 0; |
| return *this; |
| case nan: |
| i_ = nan; |
| return *this; |
| case pos_inf: |
| if (i_ < 0) |
| i_ = neg_inf; |
| else |
| i_ = pos_inf; |
| return *this; |
| case neg_inf: |
| if (i_ < 0) |
| i_ = pos_inf; |
| else |
| i_ = neg_inf; |
| return *this; |
| } |
| int s = (i_ < 0 ? -1 : 1) * (x.i_ < 0 ? -1 : 1); |
| i_ = i_ < 0 ? -i_ : i_; |
| int_type x_i_ = x.i_ < 0 ? -x.i_ : x.i_; |
| if (i_ <= pos_inf / x_i_) |
| i_ *= x_i_; |
| else |
| i_ = pos_inf; |
| i_ *= s; |
| return *this; |
| } |
| |
| template <class I> |
| saturate<I>& |
| saturate<I>::operator/=(saturate x) |
| { |
| switch (x.i_) |
| { |
| case pos_inf: |
| case neg_inf: |
| switch (i_) |
| { |
| case pos_inf: |
| case neg_inf: |
| case nan: |
| i_ = nan; |
| break; |
| default: |
| i_ = 0; |
| break; |
| } |
| return *this; |
| case nan: |
| i_ = nan; |
| return *this; |
| case 0: |
| switch (i_) |
| { |
| case pos_inf: |
| case neg_inf: |
| case nan: |
| return *this; |
| case 0: |
| i_ = nan; |
| return *this; |
| } |
| if (i_ > 0) |
| i_ = pos_inf; |
| else |
| i_ = neg_inf; |
| return *this; |
| } |
| switch (i_) |
| { |
| case 0: |
| case nan: |
| return *this; |
| case pos_inf: |
| case neg_inf: |
| if (x.i_ < 0) |
| i_ = -i_; |
| return *this; |
| } |
| i_ /= x.i_; |
| return *this; |
| } |
| |
| template <class I> |
| saturate<I>& |
| saturate<I>::operator%=(saturate x) |
| { |
| <font color="#c80000">// *this -= *this / x * x; // definition</font> |
| switch (x.i_) |
| { |
| case nan: |
| case neg_inf: |
| case 0: |
| case pos_inf: |
| i_ = nan; |
| return *this; |
| } |
| switch (i_) |
| { |
| case neg_inf: |
| case pos_inf: |
| i_ = nan; |
| case nan: |
| return *this; |
| } |
| i_ %= x.i_; |
| return *this; |
| } |
| |
| <font color="#c80000">// Demo overflow-safe integral durations ranging from picoseconds resolution to millennium resolution</font> |
| typedef std::datetime::duration<saturate<long long>, std::pico > picoseconds; |
| typedef std::datetime::duration<saturate<long long>, std::nano > nanoseconds; |
| typedef std::datetime::duration<saturate<long long>, std::micro > microseconds; |
| typedef std::datetime::duration<saturate<long long>, std::milli > milliseconds; |
| typedef std::datetime::duration<saturate<long long> > seconds; |
| typedef std::datetime::duration<saturate<long long>, std::ratio< 60LL> > minutes; |
| typedef std::datetime::duration<saturate<long long>, std::ratio< 3600LL> > hours; |
| typedef std::datetime::duration<saturate<long long>, std::ratio< 86400LL> > days; |
| typedef std::datetime::duration<saturate<long long>, std::ratio< 31556952LL> > years; |
| typedef std::datetime::duration<saturate<long long>, std::ratio<31556952000LL> > millennium; |
| |
| } <font color="#c80000">// User2</font> |
| |
| <font color="#c80000">// Demonstrate custom promotion rules (needed only if there are no implicit conversions)</font> |
| namespace User2 { namespace detail { |
| |
| template <class T1, class T2, bool = tmp::is_integral<T1>::value> |
| struct promote_helper; |
| |
| template <class T1, class T2> |
| struct promote_helper<T1, saturate<T2>, true> <font color="#c80000">// integral</font> |
| { |
| typedef typename std::common_type<T1, T2>::type rep; |
| typedef User2::saturate<rep> type; |
| }; |
| |
| template <class T1, class T2> |
| struct promote_helper<T1, saturate<T2>, false> <font color="#c80000">// floating</font> |
| { |
| typedef T1 type; |
| }; |
| |
| } } |
| |
| namespace std |
| { |
| |
| template <class T1, class T2> |
| struct common_type<User2::saturate<T1>, User2::saturate<T2> > |
| { |
| typedef typename common_type<T1, T2>::type rep; |
| typedef User2::saturate<rep> type; |
| }; |
| |
| template <class T1, class T2> |
| struct common_type<T1, User2::saturate<T2> > |
| : User2::detail::promote_helper<T1, User2::saturate<T2> > {}; |
| |
| template <class T1, class T2> |
| struct common_type<User2::saturate<T1>, T2> |
| : User2::detail::promote_helper<T2, User2::saturate<T1> > {}; |
| |
| |
| <font color="#c80000">// Demonstrate specialization of duration_values:</font> |
| |
| namespace datetime { |
| |
| template <class I> |
| struct duration_values<User2::saturate<I> > |
| { |
| typedef User2::saturate<I> Rep; |
| public: |
| static Rep zero() {return Rep(0);} |
| static Rep max() {return Rep(Rep::pos_inf-1);} |
| static Rep min() {return -max();} |
| }; |
| |
| } |
| |
| } |
| |
| #include <iostream> |
| |
| void testUser2() |
| { |
| std::cout << "*************\n"; |
| std::cout << "* testUser2 *\n"; |
| std::cout << "*************\n"; |
| using namespace User2; |
| typedef seconds::rep sat; |
| years yr(sat(100)); |
| std::cout << "100 years expressed as years = " << yr.count() << '\n'; |
| nanoseconds ns = yr; |
| std::cout << "100 years expressed as nanoseconds = " << ns.count() << '\n'; |
| ns += yr; |
| std::cout << "200 years expressed as nanoseconds = " << ns.count() << '\n'; |
| ns += yr; |
| std::cout << "300 years expressed as nanoseconds = " << ns.count() << '\n'; |
| <font color="#c80000">// yr = ns; // does not compile</font> |
| std::cout << "yr = ns; <font color="#c80000">// does not compile\n";</font> |
| <font color="#c80000">// picoseconds ps1 = yr; // does not compile, compile-time overflow in ratio arithmetic</font> |
| std::cout << "ps = yr; <font color="#c80000">// does not compile\n";</font> |
| ns = yr; |
| picoseconds ps = ns; |
| std::cout << "100 years expressed as picoseconds = " << ps.count() << '\n'; |
| ps = ns / sat(1000); |
| std::cout << "0.1 years expressed as picoseconds = " << ps.count() << '\n'; |
| yr = years(sat(-200000000)); |
| std::cout << "200 million years ago encoded in years: " << yr.count() << '\n'; |
| days d = std::datetime::duration_cast<days>(yr); |
| std::cout << "200 million years ago encoded in days: " << d.count() << '\n'; |
| millennium c = std::datetime::duration_cast<millennium>(yr); |
| std::cout << "200 million years ago encoded in millennium: " << c.count() << '\n'; |
| std::cout << "Demonstrate \"uninitialized protection\" behavior:\n"; |
| seconds sec; |
| for (++sec; sec < seconds(sat(10)); ++sec) |
| ; |
| std::cout << sec.count() << '\n'; |
| std::cout << "\n"; |
| } |
| |
| void testStdUser() |
| { |
| std::cout << "***************\n"; |
| std::cout << "* testStdUser *\n"; |
| std::cout << "***************\n"; |
| using namespace std::datetime; |
| hours hr = hours(100); |
| std::cout << "100 hours expressed as hours = " << hr.count() << '\n'; |
| nanoseconds ns = hr; |
| std::cout << "100 hours expressed as nanoseconds = " << ns.count() << '\n'; |
| ns += hr; |
| std::cout << "200 hours expressed as nanoseconds = " << ns.count() << '\n'; |
| ns += hr; |
| std::cout << "300 hours expressed as nanoseconds = " << ns.count() << '\n'; |
| <font color="#c80000">// hr = ns; // does not compile</font> |
| std::cout << "hr = ns; <font color="#c80000">// does not compile\n";</font> |
| <font color="#c80000">// hr * ns; // does not compile</font> |
| std::cout << "hr * ns; <font color="#c80000">// does not compile\n";</font> |
| duration<double> fs(2.5); |
| std::cout << "duration<double> has count() = " << fs.count() << '\n'; |
| <font color="#c80000">// seconds sec = fs; // does not compile</font> |
| std::cout << "seconds sec = duration<double> won't compile\n"; |
| seconds sec = duration_cast<seconds>(fs); |
| std::cout << "seconds has count() = " << sec.count() << '\n'; |
| std::cout << "\n"; |
| } |
| |
| <font color="#c80000">// timeval clock demo</font> |
| <font color="#c80000">// Demonstrate the use of a timeval-like struct to be used as the representation</font> |
| <font color="#c80000">// type for both duraiton and time_point.</font> |
| |
| namespace timeval_demo |
| { |
| |
| class xtime { |
| private: |
| long tv_sec; |
| long tv_usec; |
| |
| void fixup() { |
| if (tv_usec < 0) { |
| tv_usec += 1000000; |
| --tv_sec; |
| } |
| } |
| |
| public: |
| |
| explicit xtime(long sec, long usec) { |
| tv_sec = sec; |
| tv_usec = usec; |
| if (tv_usec < 0 || tv_usec >= 1000000) { |
| tv_sec += tv_usec / 1000000; |
| tv_usec %= 1000000; |
| fixup(); |
| } |
| } |
| |
| explicit xtime(long long usec) |
| { |
| tv_usec = static_cast<long>(usec % 1000000); |
| tv_sec = static_cast<long>(usec / 1000000); |
| fixup(); |
| } |
| |
| <font color="#c80000">// explicit</font> |
| operator long long() const {return static_cast<long long>(tv_sec) * 1000000 + tv_usec;} |
| |
| xtime& operator += (xtime rhs) { |
| tv_sec += rhs.tv_sec; |
| tv_usec += rhs.tv_usec; |
| if (tv_usec >= 1000000) { |
| tv_usec -= 1000000; |
| ++tv_sec; |
| } |
| return *this; |
| } |
| |
| xtime& operator -= (xtime rhs) { |
| tv_sec -= rhs.tv_sec; |
| tv_usec -= rhs.tv_usec; |
| fixup(); |
| return *this; |
| } |
| |
| xtime& operator %= (xtime rhs) { |
| long long t = tv_sec * 1000000 + tv_usec; |
| long long r = rhs.tv_sec * 1000000 + rhs.tv_usec; |
| t %= r; |
| tv_sec = t / 1000000; |
| tv_usec = t % 1000000; |
| fixup(); |
| return *this; |
| } |
| |
| friend xtime operator+(xtime x, xtime y) {return x += y;} |
| friend xtime operator-(xtime x, xtime y) {return x -= y;} |
| friend xtime operator%(xtime x, xtime y) {return x %= y;} |
| |
| friend bool operator==(xtime x, xtime y) |
| { return (x.tv_sec == y.tv_sec && x.tv_usec == y.tv_usec); } |
| |
| friend bool operator<(xtime x, xtime y) { |
| if (x.tv_sec == y.tv_sec) |
| return (x.tv_usec < y.tv_usec); |
| return (x.tv_sec < y.tv_sec); |
| } |
| |
| friend bool operator!=(xtime x, xtime y) { return !(x == y); } |
| friend bool operator> (xtime x, xtime y) { return y < x; } |
| friend bool operator<=(xtime x, xtime y) { return !(y < x); } |
| friend bool operator>=(xtime x, xtime y) { return !(x < y); } |
| |
| friend std::ostream& operator<<(std::ostream& os, xtime x) |
| {return os << '{' << x.tv_sec << ',' << x.tv_usec << '}';} |
| }; |
| |
| class xtime_clock |
| { |
| public: |
| typedef xtime rep; |
| typedef std::micro period; |
| typedef std::datetime::duration<rep, period> duration; |
| typedef std::datetime::time_point<xtime_clock> time_point; |
| |
| static time_point now(); |
| }; |
| |
| xtime_clock::time_point |
| xtime_clock::now() |
| { |
| time_point t(duration(xtime(0))); |
| gettimeofday((timeval*)&t, 0); |
| return t; |
| } |
| |
| void test_xtime_clock() |
| { |
| using namespace std::datetime; |
| std::cout << "timeval_demo system clock test\n"; |
| std::cout << "sizeof xtime_clock::time_point = " << sizeof(xtime_clock::time_point) << '\n'; |
| std::cout << "sizeof xtime_clock::duration = " << sizeof(xtime_clock::duration) << '\n'; |
| std::cout << "sizeof xtime_clock::rep = " << sizeof(xtime_clock::rep) << '\n'; |
| xtime_clock::duration delay(milliseconds(5)); |
| xtime_clock::time_point start = xtime_clock::now(); |
| while (xtime_clock::now() - start <= delay) |
| ; |
| xtime_clock::time_point stop = xtime_clock::now(); |
| xtime_clock::duration elapsed = stop - start; |
| std::cout << "paused " << nanoseconds(elapsed).count() << " nanoseconds\n"; |
| } |
| |
| } <font color="#c80000">// timeval_demo</font> |
| |
| <font color="#c80000">// Handle duration with resolution not known until run time</font> |
| |
| namespace runtime_resolution |
| { |
| |
| class duration |
| { |
| public: |
| typedef long long rep; |
| private: |
| rep rep_; |
| |
| static const double ticks_per_nanosecond; |
| |
| public: |
| typedef std::datetime::duration<double, std::nano> tonanosec; |
| |
| duration() {} <font color="#c80000">// = default;</font> |
| explicit duration(const rep& r) : rep_(r) {} |
| |
| <font color="#c80000">// conversions</font> |
| explicit duration(const tonanosec& d) |
| : rep_(static_cast<rep>(d.count() * ticks_per_nanosecond)) {} |
| |
| <font color="#c80000">// explicit</font> |
| operator tonanosec() const {return tonanosec(rep_/ticks_per_nanosecond);} |
| |
| <font color="#c80000">// observer</font> |
| |
| rep count() const {return rep_;} |
| |
| <font color="#c80000">// arithmetic</font> |
| |
| duration& operator+=(const duration& d) {rep_ += d.rep_; return *this;} |
| duration& operator-=(const duration& d) {rep_ += d.rep_; return *this;} |
| duration& operator*=(rep rhs) {rep_ *= rhs; return *this;} |
| duration& operator/=(rep rhs) {rep_ /= rhs; return *this;} |
| |
| duration operator+() const {return *this;} |
| duration operator-() const {return duration(-rep_);} |
| duration& operator++() {++rep_; return *this;} |
| duration operator++(int) {return duration(rep_++);} |
| duration& operator--() {--rep_; return *this;} |
| duration operator--(int) {return duration(rep_--);} |
| |
| friend duration operator+(duration x, duration y) {return x += y;} |
| friend duration operator-(duration x, duration y) {return x -= y;} |
| friend duration operator*(duration x, rep y) {return x *= y;} |
| friend duration operator*(rep x, duration y) {return y *= x;} |
| friend duration operator/(duration x, rep y) {return x /= y;} |
| |
| friend bool operator==(duration x, duration y) {return x.rep_ == y.rep_;} |
| friend bool operator!=(duration x, duration y) {return !(x == y);} |
| friend bool operator< (duration x, duration y) {return x.rep_ < y.rep_;} |
| friend bool operator<=(duration x, duration y) {return !(y < x);} |
| friend bool operator> (duration x, duration y) {return y < x;} |
| friend bool operator>=(duration x, duration y) {return !(x < y);} |
| }; |
| |
| static |
| double |
| init_duration() |
| { |
| mach_timebase_info_data_t MachInfo; |
| mach_timebase_info(&MachInfo); |
| return static_cast<double>(MachInfo.denom) / MachInfo.numer; |
| } |
| |
| const double duration::ticks_per_nanosecond = init_duration(); |
| |
| class clock; |
| |
| class time_point |
| { |
| public: |
| typedef runtime_resolution::clock clock; |
| typedef long long rep; |
| private: |
| rep rep_; |
| |
| |
| rep count() const {return rep_;} |
| public: |
| |
| time_point() : rep_(0) {} |
| explicit time_point(const duration& d) |
| : rep_(d.count()) {} |
| |
| <font color="#c80000">// arithmetic</font> |
| |
| time_point& operator+=(const duration& d) {rep_ += d.count(); return *this;} |
| time_point& operator-=(const duration& d) {rep_ -= d.count(); return *this;} |
| |
| friend time_point operator+(time_point x, duration y) {return x += y;} |
| friend time_point operator+(duration x, time_point y) {return y += x;} |
| friend time_point operator-(time_point x, duration y) {return x -= y;} |
| friend duration operator-(time_point x, time_point y) {return duration(x.rep_ - y.rep_);} |
| }; |
| |
| class clock |
| { |
| public: |
| typedef duration::rep rep; |
| typedef runtime_resolution::duration duration; |
| typedef runtime_resolution::time_point time_point; |
| |
| static time_point now() {return time_point(duration(mach_absolute_time()));} |
| }; |
| |
| void test() |
| { |
| using namespace std::datetime; |
| std::cout << "runtime_resolution test\n"; |
| clock::duration delay(std::datetime::milliseconds(5)); |
| clock::time_point start = clock::now(); |
| while (clock::now() - start <= delay) |
| ; |
| clock::time_point stop = clock::now(); |
| clock::duration elapsed = stop - start; |
| std::cout << "paused " << nanoseconds(duration_cast<nanoseconds>(duration::tonanosec(elapsed))).count() |
| << " nanoseconds\n"; |
| } |
| |
| } <font color="#c80000">// runtime_resolution</font> |
| |
| <font color="#c80000">// miscellaneous tests and demos:</font> |
| |
| #include <cassert> |
| #include <iostream> |
| |
| using namespace std::datetime; |
| |
| void physics_function(duration<double> d) |
| { |
| std::cout << "d = " << d.count() << '\n'; |
| } |
| |
| void drive_physics_function() |
| { |
| physics_function(nanoseconds(3)); |
| physics_function(hours(3)); |
| physics_function(duration<double>(2./3)); |
| std::cout.precision(16); |
| physics_function( hours(3) + nanoseconds(-3) ); |
| } |
| |
| void test_range() |
| { |
| using namespace std::datetime; |
| hours h1 = hours(24 * ( 365 * 292 + 292/4)); |
| nanoseconds n1 = h1 + nanoseconds(1); |
| nanoseconds delta = n1 - h1; |
| std::cout << "292 years of hours = " << h1.count() << "hr\n"; |
| std::cout << "Add a nanosecond = " << n1.count() << "ns\n"; |
| std::cout << "Find the difference = " << delta.count() << "ns\n"; |
| } |
| |
| void test_extended_range() |
| { |
| using namespace std::datetime; |
| hours h1 = hours(24 * ( 365 * 244000 + 244000/4)); |
| <font color="#c80000">/*auto*/</font> microseconds u1 = h1 + microseconds(1); |
| <font color="#c80000">/*auto*/</font> microseconds delta = u1 - h1; |
| std::cout << "244,000 years of hours = " << h1.count() << "hr\n"; |
| std::cout << "Add a microsecond = " << u1.count() << "us\n"; |
| std::cout << "Find the difference = " << delta.count() << "us\n"; |
| } |
| |
| template <class Rep, class Period> |
| void inspect_duration(std::datetime::duration<Rep, Period> d, const std::string& name) |
| { |
| typedef std::datetime::duration<Rep, Period> Duration; |
| std::cout << "********* " << name << " *********\n"; |
| std::cout << "The period of " << name << " is " << (double)Period::num/Period::den << " seconds.\n"; |
| std::cout << "The frequency of " << name << " is " << (double)Period::den/Period::num << " Hz.\n"; |
| std::cout << "The representation is "; |
| if (tmp::is_floating_point<Rep>::value) |
| { |
| std::cout << "floating point\n"; |
| std::cout << "The precision is the most significant "; |
| std::cout << std::numeric_limits<Rep>::digits10 << " decimal digits.\n"; |
| } |
| else if (tmp::is_integral<Rep>::value) |
| { |
| std::cout << "integral\n"; |
| d = Duration(Rep(1)); |
| std::datetime::duration<double> dsec = d; |
| std::cout << "The precision is " << dsec.count() << " seconds.\n"; |
| } |
| else |
| { |
| std::cout << "a class type\n"; |
| d = Duration(Rep(1)); |
| std::datetime::duration<double> dsec = d; |
| std::cout << "The precision is " << dsec.count() << " seconds.\n"; |
| } |
| d = Duration(std::numeric_limits<Rep>::max()); |
| using namespace std::datetime; |
| using namespace std; |
| typedef duration<double, ratio_multiply<ratio<24*3652425,10000>, hours::period>::type> Years; |
| Years years = d; |
| std::cout << "The range is +/- " << years.count() << " years.\n"; |
| std::cout << "sizeof(" << name << ") = " << sizeof(d) << '\n'; |
| } |
| |
| void inspect_all() |
| { |
| using namespace std::datetime; |
| std::cout.precision(6); |
| inspect_duration(nanoseconds(), "nanoseconds"); |
| inspect_duration(microseconds(), "microseconds"); |
| inspect_duration(milliseconds(), "milliseconds"); |
| inspect_duration(seconds(), "seconds"); |
| inspect_duration(minutes(), "minutes"); |
| inspect_duration(hours(), "hours"); |
| inspect_duration(duration<double>(), "duration<double>"); |
| } |
| |
| void test_milliseconds() |
| { |
| using namespace std::datetime; |
| milliseconds ms(250); |
| ms += milliseconds(1); |
| milliseconds ms2(150); |
| milliseconds msdiff = ms - ms2; |
| if (msdiff == milliseconds(101)) |
| std::cout << "success\n"; |
| else |
| std::cout << "failure: " << msdiff.count() << '\n'; |
| } |
| |
| using namespace std; |
| using namespace std::datetime; |
| |
| <font color="#c80000">// Example round_up utility: converts d to To, rounding up for inexact conversions</font> |
| <font color="#c80000">// Being able to *easily* write this function is a major feature!</font> |
| template <class To, class Rep, class Period> |
| To |
| round_up(duration<Rep, Period> d) |
| { |
| To result = duration_cast<To>(d); |
| if (result < d) |
| ++result; |
| return result; |
| } |
| |
| <font color="#c80000">// demonstrate interaction with xtime-like facility:</font> |
| |
| using namespace std::datetime; |
| |
| struct xtime |
| { |
| long sec; |
| unsigned long usec; |
| }; |
| |
| template <class Rep, class Period> |
| xtime |
| to_xtime_truncate(duration<Rep, Period> d) |
| { |
| xtime xt; |
| xt.sec = duration_cast<seconds>(d).count(); |
| xt.usec = duration_cast<microseconds>(d - seconds(xt.sec)).count(); |
| return xt; |
| } |
| |
| template <class Rep, class Period> |
| xtime |
| to_xtime_round_up(duration<Rep, Period> d) |
| { |
| xtime xt; |
| xt.sec = duration_cast<seconds>(d).count(); |
| xt.usec = round_up<microseconds>(d - seconds(xt.sec)).count(); |
| return xt; |
| } |
| |
| microseconds |
| from_xtime(xtime xt) |
| { |
| return seconds(xt.sec) + microseconds(xt.usec); |
| } |
| |
| void print(xtime xt) |
| { |
| cout << '{' << xt.sec << ',' << xt.usec << "}\n"; |
| } |
| |
| void test_with_xtime() |
| { |
| cout << "test_with_xtime\n"; |
| xtime xt = to_xtime_truncate(seconds(3) + milliseconds(251)); |
| print(xt); |
| milliseconds ms = duration_cast<milliseconds>(from_xtime(xt)); |
| cout << ms.count() << " milliseconds\n"; |
| xt = to_xtime_round_up(ms); |
| print(xt); |
| xt = to_xtime_truncate(seconds(3) + nanoseconds(999)); |
| print(xt); |
| xt = to_xtime_round_up(seconds(3) + nanoseconds(999)); |
| print(xt); |
| } |
| |
| void test_system_clock() |
| { |
| cout << "system_clock test" << endl; |
| system_clock::duration delay = milliseconds(5); |
| system_clock::time_point start = system_clock::now(); |
| while (system_clock::now() - start <= delay) |
| ; |
| system_clock::time_point stop = system_clock::now(); |
| system_clock::duration elapsed = stop - start; |
| cout << "paused " << nanoseconds(elapsed).count() << " nanoseconds\n"; |
| start = system_clock::now(); |
| stop = system_clock::now(); |
| cout << "system_clock resolution estimate: " << nanoseconds(stop-start).count() << " nanoseconds\n"; |
| } |
| |
| void test_monotonic_clock() |
| { |
| cout << "monotonic_clock test" << endl; |
| monotonic_clock::duration delay = milliseconds(5); |
| monotonic_clock::time_point start = monotonic_clock::now(); |
| while (monotonic_clock::now() - start <= delay) |
| ; |
| monotonic_clock::time_point stop = monotonic_clock::now(); |
| monotonic_clock::duration elapsed = stop - start; |
| cout << "paused " << nanoseconds(elapsed).count() << " nanoseconds\n"; |
| start = monotonic_clock::now(); |
| stop = monotonic_clock::now(); |
| cout << "monotonic_clock resolution estimate: " << nanoseconds(stop-start).count() << " nanoseconds\n"; |
| } |
| |
| void test_hi_resolution_clock() |
| { |
| cout << "high_resolution_clock test" << endl; |
| high_resolution_clock::duration delay = milliseconds(5); |
| high_resolution_clock::time_point start = high_resolution_clock::now(); |
| while (high_resolution_clock::now() - start <= delay) |
| ; |
| high_resolution_clock::time_point stop = high_resolution_clock::now(); |
| high_resolution_clock::duration elapsed = stop - start; |
| cout << "paused " << nanoseconds(elapsed).count() << " nanoseconds\n"; |
| start = high_resolution_clock::now(); |
| stop = high_resolution_clock::now(); |
| cout << "high_resolution_clock resolution estimate: " << nanoseconds(stop-start).count() << " nanoseconds\n"; |
| } |
| |
| void test_mixed_clock() |
| { |
| cout << "mixed clock test" << endl; |
| high_resolution_clock::time_point hstart = high_resolution_clock::now(); |
| cout << "Add 5 milliseconds to a high_resolution_clock::time_point\n"; |
| monotonic_clock::time_point mend = hstart + milliseconds(5); |
| bool b = hstart == mend; |
| system_clock::time_point sstart = system_clock::now(); |
| std::cout << "Subtracting system_clock::time_point from monotonic_clock::time_point doesn't compile\n"; |
| <font color="#c80000">// mend - sstart; // doesn't compile</font> |
| cout << "subtract high_resolution_clock::time_point from monotonic_clock::time_point" |
| " and add that to a system_clock::time_point\n"; |
| system_clock::time_point send = sstart + duration_cast<system_clock::duration>(mend - hstart); |
| cout << "subtract two system_clock::time_point's and output that in microseconds:\n"; |
| microseconds ms = send - sstart; |
| cout << ms.count() << " microseconds\n"; |
| } |
| |
| void test_c_mapping() |
| { |
| cout << "C map test\n"; |
| using namespace std::datetime; |
| system_clock::time_point t1 = system_clock::now(); |
| std::time_t c_time = system_clock::to_time_t(t1); |
| std::tm* tmptr = std::localtime(&c_time); |
| std::cout << "It is now " << tmptr->tm_hour << ':' << tmptr->tm_min << ':' << tmptr->tm_sec << ' ' |
| << tmptr->tm_year + 1900 << '-' << tmptr->tm_mon + 1 << '-' << tmptr->tm_mday << '\n'; |
| c_time = std::mktime(tmptr); |
| system_clock::time_point t2 = system_clock::from_time_t(c_time); |
| microseconds ms = t1 - t2; |
| std::cout << "Round-tripping through the C interface truncated the precision by " << ms.count() << " microseconds\n"; |
| } |
| |
| void test_duration_division() |
| { |
| cout << hours(3) / milliseconds(5) << '\n'; |
| cout << milliseconds(5) / hours(3) << '\n'; |
| cout << hours(1) / milliseconds(1) << '\n'; |
| } |
| |
| namespace I_dont_like_the_default_duration_behavior |
| { |
| |
| <font color="#c80000">// Here's how you override the duration's default constructor to do anything you want (in this case zero)</font> |
| |
| template <class R> |
| class zero_default |
| { |
| public: |
| typedef R rep; |
| |
| private: |
| rep rep_; |
| public: |
| zero_default(rep i = 0) : rep_(i) {} |
| operator rep() const {return rep_;} |
| |
| zero_default& operator+=(zero_default x) {rep_ += x.rep_; return *this;} |
| zero_default& operator-=(zero_default x) {rep_ -= x.rep_; return *this;} |
| zero_default& operator*=(zero_default x) {rep_ *= x.rep_; return *this;} |
| zero_default& operator/=(zero_default x) {rep_ /= x.rep_; return *this;} |
| |
| zero_default operator+ () const {return *this;} |
| zero_default operator- () const {return zero_default(-rep_);} |
| zero_default& operator++() {++rep_; return *this;} |
| zero_default operator++(int) {return zero_default(rep_++);} |
| zero_default& operator--() {--rep_; return *this;} |
| zero_default operator--(int) {return zero_default(rep_--);} |
| |
| friend zero_default operator+(zero_default x, zero_default y) {return x += y;} |
| friend zero_default operator-(zero_default x, zero_default y) {return x -= y;} |
| friend zero_default operator*(zero_default x, zero_default y) {return x *= y;} |
| friend zero_default operator/(zero_default x, zero_default y) {return x /= y;} |
| |
| friend bool operator==(zero_default x, zero_default y) {return x.rep_ == y.rep_;} |
| friend bool operator!=(zero_default x, zero_default y) {return !(x == y);} |
| friend bool operator< (zero_default x, zero_default y) {return x.rep_ < y.rep_;} |
| friend bool operator<=(zero_default x, zero_default y) {return !(y < x);} |
| friend bool operator> (zero_default x, zero_default y) {return y < x;} |
| friend bool operator>=(zero_default x, zero_default y) {return !(x < y);} |
| }; |
| |
| typedef std::datetime::duration<zero_default<long long>, std::nano > nanoseconds; |
| typedef std::datetime::duration<zero_default<long long>, std::micro > microseconds; |
| typedef std::datetime::duration<zero_default<long long>, std::milli > milliseconds; |
| typedef std::datetime::duration<zero_default<long long> > seconds; |
| typedef std::datetime::duration<zero_default<long long>, std::ratio<60> > minutes; |
| typedef std::datetime::duration<zero_default<long long>, std::ratio<3600> > hours; |
| |
| void test() |
| { |
| milliseconds ms; |
| cout << ms.count() << '\n'; |
| } |
| |
| } <font color="#c80000">// I_dont_like_the_default_duration_behavior</font> |
| |
| <font color="#c80000">// Build a min for two time_points</font> |
| |
| template <class Rep, class Period> |
| void |
| print_duration(ostream& os, duration<Rep, Period> d) |
| { |
| os << d.count() << " * " << Period::num << '/' << Period::den << " seconds\n"; |
| } |
| |
| <font color="#c80000">// Example min utility: returns the earliest time_point</font> |
| <font color="#c80000">// Being able to *easily* write this function is a major feature!</font> |
| template <class Clock, class Duration1, class Duration2> |
| inline |
| typename common_type<time_point<Clock, Duration1>, time_point<Clock, Duration2> >::type |
| min(time_point<Clock, Duration1> t1, time_point<Clock, Duration2> t2) |
| { |
| return t2 < t1 ? t2 : t1; |
| } |
| |
| void test_min() |
| { |
| typedef time_point<system_clock, common_type<system_clock::duration, seconds>::type> T1; |
| typedef time_point<system_clock, common_type<system_clock::duration, nanoseconds>::type> T2; |
| typedef common_type<T1, T2>::type T3; |
| <font color="#c80000">/*auto*/</font> T1 t1 = system_clock::now() + seconds(3); |
| <font color="#c80000">/*auto*/</font> T2 t2 = system_clock::now() + nanoseconds(3); |
| <font color="#c80000">/*auto*/</font> T3 t3 = min(t1, t2); |
| print_duration(cout, t1 - t3); |
| print_duration(cout, t2 - t3); |
| } |
| |
| void explore_limits() |
| { |
| typedef duration<long long, ratio_multiply<ratio<24*3652425,10000>, hours::period>::type> Years; |
| monotonic_clock::time_point t1( Years(250)); |
| monotonic_clock::time_point t2(-Years(250)); |
| <font color="#c80000">// nanosecond resolution is likely to overflow. "up cast" to microseconds.</font> |
| <font color="#c80000">// The "up cast" trades precision for range.</font> |
| microseconds d = time_point_cast<microseconds>(t1) - time_point_cast<microseconds>(t2); |
| cout << d.count() << " microseconds\n"; |
| } |
| |
| void manipulate_clock_object(system_clock clock) |
| { |
| system_clock::duration delay = milliseconds(5); |
| system_clock::time_point start = clock.now(); |
| while (clock.now() - start <= delay) |
| ; |
| system_clock::time_point stop = clock.now(); |
| system_clock::duration elapsed = stop - start; |
| cout << "paused " << nanoseconds(elapsed).count() << " nanoseconds\n"; |
| }; |
| |
| template <long long speed> |
| struct cycle_count |
| { |
| typedef typename ratio_multiply<ratio<speed>, mega>::type frequency; <font color="#c80000">// Mhz</font> |
| typedef typename ratio_divide<ratio<1>, frequency>::type period; |
| typedef long long rep; |
| typedef std::datetime::duration<rep, period> duration; |
| typedef std::datetime::time_point<cycle_count> time_point; |
| |
| static time_point now() |
| { |
| static long long tick = 0; |
| <font color="#c80000">// return exact cycle count</font> |
| return time_point(duration(++tick)); <font color="#c80000">// fake access to clock cycle count</font> |
| } |
| }; |
| |
| template <long long speed> |
| struct approx_cycle_count |
| { |
| static const long long frequency = speed * 1000000; <font color="#c80000">// MHz</font> |
| typedef nanoseconds duration; |
| typedef duration::rep rep; |
| typedef duration::period period; |
| static const long long nanosec_per_sec = period::den; |
| typedef std::datetime::time_point<approx_cycle_count> time_point; |
| |
| static time_point now() |
| { |
| static long long tick = 0; |
| <font color="#c80000">// return cycle count as an approximate number of nanoseconds</font> |
| <font color="#c80000">// compute as if nanoseconds is only duration in the std::lib</font> |
| return time_point(duration(++tick * nanosec_per_sec / frequency)); |
| } |
| }; |
| |
| void cycle_count_delay() |
| { |
| { |
| typedef cycle_count<400> clock; |
| cout << "\nSimulated " << clock::frequency::num / mega::num << "MHz clock which has a tick period of " |
| << duration<double, nano>(clock::duration(1)).count() << " nanoseconds\n"; |
| nanoseconds delayns(500); |
| clock::duration delay = duration_cast<clock::duration>(delayns); |
| cout << "delay = " << delayns.count() << " nanoseconds which is " << delay.count() << " cycles\n"; |
| clock::time_point start = clock::now(); |
| clock::time_point stop = start + delay; |
| while (clock::now() < stop) <font color="#c80000">// no multiplies or divides in this loop</font> |
| ; |
| clock::time_point end = clock::now(); |
| clock::duration elapsed = end - start; |
| cout << "paused " << elapsed.count() << " cycles "; |
| cout << "which is " << duration_cast<nanoseconds>(elapsed).count() << " nanoseconds\n"; |
| } |
| { |
| typedef approx_cycle_count<400> clock; |
| cout << "\nSimulated " << clock::frequency / 1000000 << "MHz clock modeled with nanoseconds\n"; |
| clock::duration delay = nanoseconds(500); |
| cout << "delay = " << delay.count() << " nanoseconds\n"; |
| clock::time_point start = clock::now(); |
| clock::time_point stop = start + delay; |
| while (clock::now() < stop) <font color="#c80000">// 1 multiplication and 1 division in this loop</font> |
| ; |
| clock::time_point end = clock::now(); |
| clock::duration elapsed = end - start; |
| cout << "paused " << elapsed.count() << " nanoseconds\n"; |
| } |
| { |
| typedef cycle_count<1500> clock; |
| cout << "\nSimulated " << clock::frequency::num / mega::num << "MHz clock which has a tick period of " |
| << duration<double, nano>(clock::duration(1)).count() << " nanoseconds\n"; |
| nanoseconds delayns(500); |
| clock::duration delay = duration_cast<clock::duration>(delayns); |
| cout << "delay = " << delayns.count() << " nanoseconds which is " << delay.count() << " cycles\n"; |
| clock::time_point start = clock::now(); |
| clock::time_point stop = start + delay; |
| while (clock::now() < stop) <font color="#c80000">// no multiplies or divides in this loop</font> |
| ; |
| clock::time_point end = clock::now(); |
| clock::duration elapsed = end - start; |
| cout << "paused " << elapsed.count() << " cycles "; |
| cout << "which is " << duration_cast<nanoseconds>(elapsed).count() << " nanoseconds\n"; |
| } |
| { |
| typedef approx_cycle_count<1500> clock; |
| cout << "\nSimulated " << clock::frequency / 1000000 << "MHz clock modeled with nanoseconds\n"; |
| clock::duration delay = nanoseconds(500); |
| cout << "delay = " << delay.count() << " nanoseconds\n"; |
| clock::time_point start = clock::now(); |
| clock::time_point stop = start + delay; |
| while (clock::now() < stop) <font color="#c80000">// 1 multiplication and 1 division in this loop</font> |
| ; |
| clock::time_point end = clock::now(); |
| clock::duration elapsed = end - start; |
| cout << "paused " << elapsed.count() << " nanoseconds\n"; |
| } |
| } |
| |
| void test_special_values() |
| { |
| std::cout << "duration<unsigned>::min().count() = " << duration<unsigned>::min().count() << '\n'; |
| std::cout << "duration<unsigned>::zero().count() = " << duration<unsigned>::zero().count() << '\n'; |
| std::cout << "duration<unsigned>::max().count() = " << duration<unsigned>::max().count() << '\n'; |
| std::cout << "duration<int>::min().count() = " << duration<int>::min().count() << '\n'; |
| std::cout << "duration<int>::zero().count() = " << duration<int>::zero().count() << '\n'; |
| std::cout << "duration<int>::max().count() = " << duration<int>::max().count() << '\n'; |
| } |
| |
| int main() |
| { |
| basic_examples(); |
| testStdUser(); |
| testUser1(); |
| testUser2(); |
| drive_physics_function(); |
| test_range(); |
| test_extended_range(); |
| inspect_all(); |
| test_milliseconds(); |
| test_with_xtime(); |
| test_system_clock(); |
| test_monotonic_clock(); |
| test_hi_resolution_clock(); |
| test_mixed_clock(); |
| timeval_demo::test_xtime_clock(); |
| runtime_resolution::test(); |
| test_c_mapping(); |
| test_duration_division(); |
| I_dont_like_the_default_duration_behavior::test(); |
| test_min(); |
| #if VARIADIC_COMMON_TYPE |
| inspect_duration(common_type<duration<double>, hours, microseconds>::type(), |
| "common_type<duration<double>, hours, microseconds>::type"); |
| #endif |
| explore_limits(); |
| manipulate_clock_object(system_clock()); |
| duration<double, milli> d = milliseconds(3) * 2.5; |
| inspect_duration(milliseconds(3) * 2.5, "milliseconds(3) * 2.5"); |
| cout << d.count() << '\n'; |
| <font color="#c80000">// milliseconds ms(3.5); // doesn't compile</font> |
| cout << "milliseconds ms(3.5) doesn't compile\n"; |
| cycle_count_delay(); |
| test_special_values(); |
| } |
| |
| <font color="#c80000">/* |
| Output |
| |
| Running basic examples |
| sleep_for 3000000 microseconds |
| sleep_for 1 microseconds |
| sleep_until 10:47:17.728293 which is 4499340 microseconds away |
| try_lock_for 30000 microseconds |
| try_lock_until 10:47:17.728285 which is 4499303 microseconds away |
| wait_for 60000000 microseconds |
| wait_until 10:47:17.728285 which is 4499264 microseconds away |
| sleep_for 250000 microseconds |
| sleep_until 10:47:14.729077 which is 1499979 microseconds away |
| *************** |
| * testStdUser * |
| *************** |
| 100 hours expressed as hours = 100 |
| 100 hours expressed as nanoseconds = 360000000000000 |
| 200 hours expressed as nanoseconds = 720000000000000 |
| 300 hours expressed as nanoseconds = 1080000000000000 |
| hr = ns; <font color="#c80000">// does not compile</font> |
| hr * ns; <font color="#c80000">// does not compile</font> |
| duration<double> has count() = 2.5 |
| seconds sec = duration<double> won't compile |
| seconds has count() = 2 |
| |
| ************* |
| * testUser1 * |
| ************* |
| Speed = 24.5872 meters/sec |
| Acceleration = 9.81456 meters/sec^2 |
| Distance = 13.5204 meters |
| There are 125/201168 miles/meter which is approximately 0.000621371 |
| There are 201168/125 meters/mile which is approximately 1609.34 |
| 1 attosecond is 1e-18 seconds |
| sec = as; <font color="#c80000">// compiles</font> |
| 1 second is 1e+18 attoseconds |
| as = sec; <font color="#c80000">// compiles</font> |
| |
| ************* |
| * testUser2 * |
| ************* |
| 100 years expressed as years = 100 |
| 100 years expressed as nanoseconds = 3155695200000000000 |
| 200 years expressed as nanoseconds = 6311390400000000000 |
| 300 years expressed as nanoseconds = inf |
| yr = ns; <font color="#c80000">// does not compile</font> |
| ps = yr; <font color="#c80000">// does not compile</font> |
| 100 years expressed as picoseconds = inf |
| 0.1 years expressed as picoseconds = 3155695200000000000 |
| 200 million years ago encoded in years: -200000000 |
| 200 million years ago encoded in days: -73048500000 |
| 200 million years ago encoded in millennium: -200000 |
| Demonstrate "uninitialized protection" behavior: |
| nan |
| |
| d = 3e-09 |
| d = 10800 |
| d = 0.666667 |
| d = 10799.999999997 |
| 292 years of hours = 2559672hr |
| Add a nanosecond = 9214819200000000001ns |
| Find the difference = 1ns |
| 244,000 years of hours = 2138904000hr |
| Add a microsecond = 7700054400000000001us |
| Find the difference = 1us |
| ********* nanoseconds ********* |
| The period of nanoseconds is 1e-09 seconds. |
| The frequency of nanoseconds is 1e+09 Hz. |
| The representation is integral |
| The precision is 1e-09 seconds. |
| The range is +/- 292.277 years. |
| sizeof(nanoseconds) = 8 |
| ********* microseconds ********* |
| The period of microseconds is 1e-06 seconds. |
| The frequency of microseconds is 1e+06 Hz. |
| The representation is integral |
| The precision is 1e-06 seconds. |
| The range is +/- 292277 years. |
| sizeof(microseconds) = 8 |
| ********* milliseconds ********* |
| The period of milliseconds is 0.001 seconds. |
| The frequency of milliseconds is 1000 Hz. |
| The representation is integral |
| The precision is 0.001 seconds. |
| The range is +/- 2.92277e+08 years. |
| sizeof(milliseconds) = 8 |
| ********* seconds ********* |
| The period of seconds is 1 seconds. |
| The frequency of seconds is 1 Hz. |
| The representation is integral |
| The precision is 1 seconds. |
| The range is +/- 2.92277e+11 years. |
| sizeof(seconds) = 8 |
| ********* minutes ********* |
| The period of minutes is 60 seconds. |
| The frequency of minutes is 0.0166667 Hz. |
| The representation is integral |
| The precision is 60 seconds. |
| The range is +/- 4083.06 years. |
| sizeof(minutes) = 4 |
| ********* hours ********* |
| The period of hours is 3600 seconds. |
| The frequency of hours is 0.000277778 Hz. |
| The representation is integral |
| The precision is 3600 seconds. |
| The range is +/- 244984 years. |
| sizeof(hours) = 4 |
| ********* duration<double> ********* |
| The period of duration<double> is 1 seconds. |
| The frequency of duration<double> is 1 Hz. |
| The representation is floating point |
| The precision is the most significant 15 decimal digits. |
| The range is +/- 5.69666e+300 years. |
| sizeof(duration<double>) = 8 |
| success |
| test_with_xtime |
| {3,251000} |
| 3251 milliseconds |
| {3,251000} |
| {3,0} |
| {3,1} |
| system_clock test |
| paused 5001000 nanoseconds |
| system_clock resolution estimate: 0 nanoseconds |
| monotonic_clock test |
| paused 5000181 nanoseconds |
| monotonic_clock resolution estimate: 97 nanoseconds |
| high_resolution_clock test |
| paused 5000277 nanoseconds |
| high_resolution_clock resolution estimate: 96 nanoseconds |
| mixed clock test |
| Add 5 milliseconds to a high_resolution_clock::time_point |
| Subtracting system_clock::time_point from monotonic_clock::time_point doesn't compile |
| subtract high_resolution_clock::time_point from monotonic_clock::time_point and add that to a system_clock::time_point |
| subtract two system_clock::time_point's and output that in microseconds: |
| 5000 microseconds |
| timeval_demo system clock test |
| sizeof xtime_clock::time_point = 8 |
| sizeof xtime_clock::duration = 8 |
| sizeof xtime_clock::rep = 8 |
| paused 5001000 nanoseconds |
| runtime_resolution test |
| paused 5000205 nanoseconds |
| C map test |
| It is now 10:47:13 2008-4-22 |
| Round-tripping through the C interface truncated the precision by 255445 microseconds |
| 2160000 |
| 0 |
| 3600000 |
| 0 |
| 2999998997 * 1/1000000000 seconds |
| 0 * 1/1000000000 seconds |
| 15778476000000000 microseconds |
| paused 5001000 nanoseconds |
| ********* milliseconds(3) * 2.5 ********* |
| The period of milliseconds(3) * 2.5 is 0.001 seconds. |
| The frequency of milliseconds(3) * 2.5 is 1000 Hz. |
| The representation is floating point |
| The precision is the most significant 15 decimal digits. |
| The range is +/- 5.69666e+297 years. |
| sizeof(milliseconds(3) * 2.5) = 8 |
| 7.5 |
| milliseconds ms(3.5) doesn't compile |
| |
| Simulated 400MHz clock which has a tick period of 2.5 nanoseconds |
| delay = 500 nanoseconds which is 200 cycles |
| paused 201 cycles which is 502 nanoseconds |
| |
| Simulated 400MHz clock modeled with nanoseconds |
| delay = 500 nanoseconds |
| paused 503 nanoseconds |
| |
| Simulated 1500MHz clock which has a tick period of 0.666667 nanoseconds |
| delay = 500 nanoseconds which is 750 cycles |
| paused 751 cycles which is 500 nanoseconds |
| |
| Simulated 1500MHz clock modeled with nanoseconds |
| delay = 500 nanoseconds |
| paused 500 nanoseconds |
| duration<unsigned>::min().count() = 0 |
| duration<unsigned>::zero().count() = 0 |
| duration<unsigned>::max().count() = 4294967295 |
| duration<int>::min().count() = -2147483647 |
| duration<int>::zero().count() = 0 |
| duration<int>::max().count() = 2147483647 |
| */</font> |
| |
| <font color="#c80000">/* |
| Example disassemblies (to show efficiency). |
| Disclaimer: I don't pretend to understand the optimizations made. |
| |
| Compiled with |
| g++ -O3 -arch x86_64 -S test2.cpp |
| |
| x86 64-bit architecture |
| |
| ******************** |
| |
| system_clock::duration |
| time_subtraction(system_clock::time_point x, system_clock::time_point y) |
| { |
| return x - y; |
| } |
| |
| pushq %rbp |
| LCFI25: |
| subq %rsi, %rdi |
| movq %rdi, %rax |
| movq %rsp, %rbp |
| LCFI26: |
| leave |
| ret |
| |
| ******************** |
| |
| seconds |
| time_subtract_to_seconds(system_clock::time_point x, system_clock::time_point y) |
| { |
| return duration_cast<seconds>(x - y); |
| } |
| |
| subq %rsi, %rdi |
| movabsq $4835703278458516699, %rdx |
| pushq %rbp |
| LCFI25: |
| movq %rdi, %rax |
| sarq $63, %rdi |
| imulq %rdx |
| movq %rsp, %rbp |
| LCFI26: |
| leave |
| sarq $18, %rdx |
| subq %rdi, %rdx |
| movq %rdx, %rax |
| ret |
| |
| ******************** |
| |
| nanoseconds |
| time_subtract_to_nanoseconds(system_clock::time_point x, system_clock::time_point y) |
| { |
| return x - y; |
| } |
| |
| pushq %rbp |
| LCFI25: |
| subq %rsi, %rdi |
| imulq $1000, %rdi, %rax |
| movq %rsp, %rbp |
| LCFI26: |
| leave |
| ret |
| |
| ******************** |
| |
| system_clock::time_point |
| time_plus_duration(system_clock::time_point x, system_clock::duration y) |
| { |
| return x + y; |
| } |
| |
| pushq %rbp |
| LCFI37: |
| movq %rsp, %rbp |
| LCFI38: |
| leaq (%rsi,%rdi), %rax |
| leave |
| ret |
| |
| ******************** |
| |
| milliseconds |
| duration_plus_duration(milliseconds x, milliseconds y) |
| { |
| return x + y; |
| } |
| |
| pushq %rbp |
| LCFI11: |
| leaq (%rdi,%rsi), %rax |
| movq %rsp, %rbp |
| LCFI12: |
| leave |
| ret |
| |
| ******************** |
| |
| nanoseconds |
| milliseconds_plus_nanoseconds(milliseconds x, nanoseconds y) |
| { |
| return x + y; |
| } |
| |
| imulq $1000000, %rdi, %rdi |
| pushq %rbp |
| LCFI20: |
| movq %rsp, %rbp |
| LCFI21: |
| leave |
| leaq (%rdi,%rsi), %rax |
| ret |
| |
| ******************** |
| |
| milliseconds |
| nanoseconds_to_milliseconds(nanoseconds x) |
| { |
| return duration_cast<milliseconds>(x); |
| } |
| |
| movq %rdi, %rax |
| movabsq $4835703278458516699, %rdx |
| pushq %rbp |
| LCFI13: |
| imulq %rdx |
| sarq $63, %rdi |
| movq %rsp, %rbp |
| LCFI14: |
| leave |
| sarq $18, %rdx |
| subq %rdi, %rdx |
| movq %rdx, %rax |
| ret |
| |
| ******************** |
| |
| nanoseconds |
| milliseconds_to_nanoseconds(milliseconds x) |
| { |
| return x; |
| } |
| |
| pushq %rbp |
| LCFI13: |
| imulq $1000000, %rdi, %rax |
| movq %rsp, %rbp |
| LCFI14: |
| leave |
| ret |
| |
| ******************** |
| |
| hours |
| increment_hours(hours x) |
| { |
| return ++x; |
| } |
| |
| pushq %rbp |
| LCFI11: |
| leaq 1(%rdi), %rax |
| movq %rsp, %rbp |
| LCFI12: |
| leave |
| ret |
| |
| */</font> |
| </pre> |
| |
| </body></html> |