3rdParty/boost/1.78.0/libs/chrono/doc/time2_demo.html
/\* 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 // optional high\_resolution\_clock // optional Much thanks to Andrei Alexandrescu, Walter Brown, Peter Dimov, Jeff Garland, Terry Golubiewski, Daniel Krügler, Anthony Williams. Synopsis namespace std { // \<type\_traits\> // common\_type // common\_type is ageneral purpose trait that can be specialized for user-defined types. // The semantics are intended to be identical to finding the resulting type of a // the conditional operator. // The client may need to specialize common\_type if he wishes to convert to or from // another type only explicitly. It is used to determine the result type // in "mixed-mode" duration and time\_point arithmetic. It will also find use in // similar "mixed-mode" arithmetic applications. template \<class T, class U\> struct common\_type { private: static T t(); static U u(); public: typedef decltype(true ? t() : u()) type; }; // or... 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; }; // This alternative variadic formulation of common\_type has some advantages: // // 1. The obvious advantage is that it can handle 3 or more arguments seamlessly. // This can come in handy when writing template functions that take more than // two arguments, such as fma(x, y, z). // // 2. We could just get rid of identity (avoiding the legacy conflict) and use // common\_type\<T\>::type in the one place we use identity\<T\>::type today. // // 3. For clients that need to specialize common\_type (such as duration and time\_point), // the client still needs to specialize only the two-argument version. The default // definition of the higher-order common\_type will automatically use the client's // specialized two-argument version. // For example: // common\_type\<duration\<double\>, hours, microseconds\>::type is duration\<double, micro\> // ... end or // The cost of not including either version of common\_type is that it is very likely that // the implementation would include it anyway, but spell it \_\_common\_type instead. This // would prevent authors of arithmetic emulators from using their classes as representations // with durations unless the emulator had exactly one implicit conversion to or from an // arithmetic type. This would be a large loss of functionality from the client's point // of view, possibly mandating a less safe interface for the client's arithmetic emulator. // ratio // ratio is a general purpose type allowing one to easily and safely compute integral // ratio values at compile time. The ratio class catches all errors (such as divide by // zero and overflow) at compile time. It is used in the duration and time\_point libraries // to efficiently create units of time. It can also be used in other "quantity" // libraries (both std-defined and user-defined), or anywhere there is an integral // ratio which is known at compile time. The use of this utility can greatly reduce // the chances of run time overflow because the ratio (and any ratios resulting from // ratio arithmetic) are always reduced to lowest terms. // The cost of not including ratio would mean that the implementor would likely have this // functionality anyway, but spell it \_\_ratio instead. This would prevent the client from // using ratio in his own code as demonstrated in the "User1" example. Furthermore duration // would have to be templated on two long long's instead of on ratio like so: // // template \<class Rep, long long N, long long D\> duration. // // This would mean that clients wanting to build a custom duration type (say a nanosecond // represented by a double) would have to write: // // duration\<double, 1, 1000000000LL\> // // instead of: // // duration\<double, nano\> // // This lack of syntatic niceness, along with the loss of functionality in the reuse of // ratio in user-written code seems to indicate that the loss of ratio would be a sizeable // loss to client code. template \<intmax\_t N, intmax\_t D = 1\> class ratio { // For every possible value of N and D, abs(N) \>= 0 and abs(D) \> 0 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; // Reduced by greatest common divisor of N and D, has sign of sign(N) \* sign(D) static const intmax\_t den; // Reduced by greatest common divisor of N and D, always positive // When num == 0, den == 1 }; // The static\_asserts in ratio are there to catch any values which have a negative absolute value. // In a typical 2's complement representation this is only LLONG\_MIN. The reason for prohibiting // this value is because ratio must take the absolute values of its arguments and generally depends // on that number being non-negative in order to maintain invariants such as den \> 0. // convenience typedefs typedef ratio\<1, 1000000000000000000000000\> yocto; // conditionally supported typedef ratio\<1, 1000000000000000000000\> zepto; // conditionally supported 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; // conditionally supported typedef ratio\<1000000000000000000000000, 1\> yotta; // conditionally supported // Compile time arithmetic and comparisons should either avoid overflow or not compile 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 { // duration customization traits // Authors of arithmetic emulation types should specialize treat\_as\_floating\_point // if their class emulates floating point and they want to use it as a duration's // representation. template \<class Rep\> struct treat\_as\_floating\_point : is\_floating\_point\<Rep\> {}; // Authors of arithmetic emulation types should specialize duration\_values // if they want to use it as a duration's representation, and the default // definition of duration\_values does not have the correct behavior. 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();} }; // Note: Rep(0) instead of Rep() is used for zero() because the author of Rep may // chose to have Rep() refer to an inderminant or unitialized value. // duration // A duration has a representation and a period. // // The representation is an arithmetic type, or a class emulating an arithmetic type. // // The period is the rational number of seconds between "ticks" of the duration. The // duration simply holds a count of the elapsed number of ticks (using the // representation), and that is related to seconds by multiplying by the period. // Note, this multiplication is only required when one needs to convert between // durations with different tick periods (e.g. milliseconds to microseconds). // // A duration has defalt construction and default copy semantics. One can also explicitly // construct a duration from its representation or something implicitly convertible to // its representation. If the representation is integral (or emulated integral) the // duration may not be constructed from a floating point (or emulated floating point) // type, even if that type is impilcitly convertible to the representation (the client // must explicitly convert such an argument as they pass it to the constructor if such // a conversion is desired). // // A duration may be implicitly constructible from another duration if the representations // of the two durations meet certain requirements. Let the representation of this duration // be Rep1 and the representation of the other duration be Rep2. Example representations // include int, long long, double, or a user-defined class which emulates one of these // arithmetic types. To qualify for implicit constructability Rep1 must be explicitly // constructible from Rep2. Note that implicit constructibility of Rep1 from Rep2 is not // required for this implicit construction between durations. Additionally the trait // common\_type\<Rep1, Rep2\>::type must be well defined. If a conditional expression involving // these two types isn't valid, there must exist a common\_type specialization which makes // the trait valid. // // The requirements put on the relationship between Rep1 and Rep2 are intended to be minimal, // and not require implicit conversions (which could be considered error prone by the author // of either of these representations). // // In addition to the above relationship between the representations, implicit constructability // also depends on whether the representation is considered floating point (or emulated floating // point) or integral (or emulated integral). // // If a duration has a floating point (or emulated floating point) representation it // is implicitly constructible from all other durations of any period (as long as // the representations are compatible as described above). // // If a duration has an integral (or emulated integral) representation it is implicitly // constructible from other integral-based durations which have a period which will exactly convert // to the period of this duration with no truncation error. More specifically, if the // period of this duration is P1, and the period of the other duration is P2, this // duration is implicitly constructible from the other duration if P2/P1 is a whole number // (as long as the representations are compatible as described above). Example: // microseconds has a period p1 = 1/1000000 seconds. milliseconds has a period // P2 = 1/1000 seconds. P2/P1 is (1/1000)/(1/1000000) = 1000000/1000 = 1000. // Therefore microseconds will implicitly construct from milliseconds (but not vice-versa). // // These rules involving integral representations are meant to prevent accidental truncatation // error. If truncation error is desired, a duration\_cast facility is available to force it. // Example: // milliseconds ms(3); // ok, ms.count() == 3, which is 0.003 seconds // microseconds us = ms; // ok, us.count() == 3000 which is 0.003000 seconds // ++us; // ok, us.count() == 3001 which is 0.003001 seconds // ms = us; // won't compile, might truncate // ms = duration\_cast\<milliseconds\>(us); // ok, ms.count() = 3, truncated a microsecond // // A duration has a single observer: rep count() const; which returns the stored // representation which holds the number of elapsed "ticks". // // A duration supports the following member arithmetic: // // duration operator+() const; // duration operator-() const; // duration& operator++(); // duration operator++(int); // duration& operator--(); // duration operator--(int); // // duration& operator+=(duration d); // duration& operator-=(duration d); // // duration& operator\*=(rep rhs); // duration& operator/=(rep rhs); // // The arithmetic simply manipulates the "tick" count in the obvious way (e.g. operator++ // increments the tick count by 1). // // A duration supports the following non-member arithmetic. // Let D1 represent duration\<Rep1, Period1\> and D2 represent duration\<Rep2, Period2\>. // // common\_type\<D1, D2\>::type operator+( D1, D2); // returns a duration // common\_type\<D1, D2\>::type operator-( D1, D2); // returns a duration // duration\<common\_type\<D1::rep,Rep2\>::type, D1::period\> operator\*( D1, Rep2); // returns a duration // duration\<common\_type\<D1::rep,Rep2\>::type, D1::period\> operator\*(Rep2, D1); // returns a duration // duration\<common\_type\<D1::rep,Rep2\>::type, D1::period\> operator/( D1, Rep2); // returns a duration // common\_type\<D1::rep, D2::rep\>::type operator/( D1, D2); // returns a scalar // // A duration D1 is fully equality and less-than comparable with any other duration D2, as // long as common\_type\<D1::rep, D2::rep\> is well defined. // Example: // milliseconds ms(3); // ms.count() == 3, which is 0.003 seconds // microseconds us = ms; // us.count() == 3000 which is 0.003000 seconds // --us; // us.count() == 2999 which is 0.002999 seconds // assert(ms != us); // 3 milliseconds is not equal to 2999 microseconds // assert(ms \> us); // 3 milliseconds is greater than 2999 microseconds // ++us; // us.count() == 3000 which is 0.003000 seconds // assert(ms == us); // 3 milliseconds is equal to 3000 microseconds // // Durations based on floating point representations are subject to round off error precisely the // same way their representations are. // // Arithmetic and comparisons among integral-based durations is not subject to truncation error or // round off error. If truncation error would result from the arithmetic (say // by converting a smaller period duration to a larger one) the expression will // not compile (unless duration\_cast is used). If one performs arithmetic // involving the duration's representation (such as division), then truncation // will happen implicitly. // // Overflow error may silently happen with a duration. The std-defined durations // have a minimum range of +/- 292 years. // // A duration is a thin wrapper around its representation. sizeof(duration\<Rep, Period\>) == sizeof(Rep). // // A duration can represent units as small as 10^-18 seconds (attoseconds) and as large as 10^18 seconds // (about 30 billion years). The range of a duration is based on the range of its representation // combined with its period. // The cost of not including the flexibility to represent different "tick periods" in the duration // type would be a great loss of both flexibility, convenience and safety for the client. For example // if had just one duration type which counted nanoseconds (no matter how that count was represented), // then clients could never have the ability to traffic in picoseconds. And the only hope of reaching // beyond a +/- 292 year range with nanoseconds is to increase the number of bits in the representation // (such as a long long). Furthermore, if the client wanted to traffic in units larger than a nanosecond // (e.g. seconds) for convience, they would likely need to set up their own conversion constants and // convert manually. // // If the conversion constants are specified at run time, rather than as compile time integral constants, // then the client suffers a significant performance penalty as for every conversion one will have to // perform both a multiplication and a division. In contrast, when converting among any two units of // the set (hours, minutes, seconds, milliseconds, microseconds, nanoseconds), there need be only a // single multiplication \*or\* division (never both). This proposal makes every unit conversion as // efficient as if it had been coded by hand (see duration\_cast). Furthermore duration\_cast encapsulates // all unit conversions within a single uniform-syntax function which is easily used in generic code. There // is no need (or motivation) to set up a "hub-and-spoke" conversion regimen, so that the number of conversion // functions is O(N) rather than O(N^2). 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\_; // exposition only public: // construction / destruction 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; // copy semantics duration(const duration&) = default; duration& operator=(const duration&) = default; // conversions 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); // observer rep count() const; // arithmetic 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); // special values static constexpr duration zero(); static constexpr duration min(); static constexpr duration max(); }; // convenience typedefs typedef duration\<int\_least64\_t, nano\> nanoseconds; // 10^-9 seconds typedef duration\<int\_least55\_t, micro\> microseconds; // 10^-6 seconds typedef duration\<int\_least45\_t, milli\> milliseconds; // 10^-3 seconds typedef duration\<int\_least35\_t \> seconds; // 1 second typedef duration\<int\_least29\_t, ratio\< 60\>\> minutes; // 60 seconds typedef duration\<int\_least23\_t, ratio\<3600\>\> hours; // 3600 seconds // duration\_cast can be used to force a conversion between two durations (assuming // the source representation can be explicitly converted to the target representation). // Not all integral-based durations are implicitly convertible to another (to // avoid accidental truncation error). When truncation error is desired, the client // uses duration\_cast to explicitly request the non-exact conversion. When // duration\_cast is used to convert between durations which have an implicit conversion, // the behavior and performance of the conversion using duration\_cast is identical to // that of the implicit conversion. template \<class ToDuration, class Rep, class Period\> requires ToDuration is an instantiation of duration ToDuration duration\_cast(const duration\<Rep, Period\>& fd); // Examples: // microseconds us(3500); // 3500 microseconds // milliseconds ms = us; // Does not compile (implicit truncation) // milliseconds ms = duration\_cast\<milliseconds\>(us); // 3 milliseconds (explicit truncation) // us = ms; // 3000 microseconds // us = duration\_cast\<microseconds\>(ms); // 3000 microseconds } // datetime // Given two durations: duration\<Rep1, Period1\> and duration\<Rep2, Period2\>, the common\_type // of those two durations is a duration with a representation of common\_type\<Rep1, Rep2\>, // and a period which is the "greatest common period" of Period1 and Period2. The GCP // (Greatest Common Period) of Period1 and Period2 is the largest period which will divide // both Period1 and Period2 evenly (and is often equivalent to the minimum of Period1 and // Period2). This can be computed (by the implementation at compile time) by // GCD(Period1::num, Period2::num) / LCM(Period1::den, Period2::den) where GCD is // "Greatest Common Divisor" and LCM is "Least Common Multiple". 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; }; // Note: For any two durations D1 and D2, they will both exactly convert to common\_type\<D1, D2\>::type. // common\_type\<D1, D2\>::type will have the largest possible period to make this possible, and // may be the same type as D1 or D2. Examples: // common\_type\<minutes, microseconds\>::type is microseconds. // common\_type\<milliseconds, microseconds\>::type is microseconds. // common\_type\<nanoseconds, microseconds\>::type is nanoseconds. // // A more complex example: // common\_type\< duration\<long, milli\>, duration\<int, ratio\<1,30\>\> \>::type is // duration\<long, ratio\<1,3000\>\>. And both duration\<long, milli\> and // duration\<int, ratio\<1,30\>\> will exactly convert to duration\<long, ratio\<1,3000\>\>. // The former multitplies its representation by 3L and the latter converts its // representation to long and multiplies that result by 1000L. There exists no // duration with a larger period such that both duration\<long, milli\> and // duration\<int, ratio\<1,30\>\> will exactly convert to it. 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); // Note: the above 3 signatures can be approximated with is\_convertible if concepts do not // make it into the language. Requiring only \*explicit\* convertibility between the Rep // types is strongly desired. One way or another, Rep2 must be constrained. Otherwise // the operators are overly generic. 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); // time\_point // A time\_point represents an epoch plus or minus a duration. The relationship between a time\_point // which represents "now" and the time\_point's epoch is obtained via a clock. Each time\_point is // tied to a specific clock. Thus, for any time\_point, one can find the duration between that // point in time and now, and between that point in time, and its epoch. // // A time\_point may be default constructed. This time\_point represents the epoch. time\_point has // default copy semantics. // // time\_point may be explicitly constructed by a duration having the same representation and period as // the time\_point. Any other duration which is implicitly convertible to the time\_point's "native" duration can // also be used to explicitly construct the time\_point. The meaning of this construction is identical to // time\_point() + d. // // A time\_point is implicitly constructible from another time\_point if they share the same clock, // and the duration of this time\_point is implicitly constructible from the duration of the other // time\_point. A time\_point constructed in this fashion will compare equal to the source time\_point // after the construction. // // A time\_point supports the following member arithmetic: // // time\_point& operator+=(duration d); // time\_point& operator-=(duration d); // // A time\_point supports the following non-member arithmetic. // Let T1 represent time\_point\<Clock, Duration1\>, // T2 represent time\_point\<Clock, Duration2\>, // and D represent duration\<Rep3, Period3\>. Note that T1 and T2 must have the same Clock. // Attempts to interoperate times having different clocks results in a compile time failure. // // T2 operator+(T1, D); // return type is a time\_point // T2 operator+( D, T1); // return type is a time\_point // T2 operator-(T1, D); // return type is a time\_point // D operator-(T1, T2); // return type is a duration // // A time\_point T1 is fully equality and less-than comparable with any other time\_point T2 which // has the same clock, and for which their durations are comparable. // // Times based on floating point representations are subject to round off error precisely the // same way their representations are. // // Times based on integral representations are not subject to truncation error or round off // error. A compile time error will result if truncation error is possible. Truncation error // is only possible with construction or the member arithmetic (and won't compile). Non-member // arithmetic and comparison is always exact. Overflow error with integral based times remains a // possibility. // // A time\_point is a thin wrapper around its representation. // sizeof(time\_point\<Clock, Duration\>) == sizeof(Duration) == sizeof(Duration::rep). // // A time\_point can represent units as small as 10^-18 seconds and as large as 10^18 seconds. The range // of a time\_point is based on the range of its representation combined with its period. // // Because no two clocks report the exact same time, even clocks which nominally have the same // epoch, are considered by this framework to have different epochs, if only by a few nanoseconds. // Converting time\_points from one clock to another will involve synchronization of the clocks, // which can be viewed as a synchronization of their epochs. Such synchronization is clock specific // and beyond the scope of this API. A future API, or a platform specific API, can easily // write such a synchronization API, basing it on this API. // The cost of not including a time\_point class is the lack of the ability to safely interact with // the concept of "epoch + duration". Without a separate type, the client is in danger of accidently // writing code that boils down to "epoch1 + duration1" + "epoch2 + duration2". Algebraically this // results in epoch1+epoch2 as a subexpression which is likely to be completely without meaning. What // would it mean to add New Years 1970 to the point in time at which your computer booted up? Or for // that matter, what is the meaning of "New Years 1970" + "New Years 1970"? // // Additionally this would force the duration type to play double duty as a time\_point leading to // client confusion. For example POSIX has timespec represent a duration in nanosleep, and yet the // same type is used as a time\_point in pthread\_cond\_timedwait and pthread\_mutex\_timedlock. The // confusion seems even more likely with a function such as clock\_nanosleep where timespec can mean // either a duration or a time\_point depending upon another argument to the function. // // In C++ we can easily mitigate such errors by detecting them at compile time. This is done through // the use of distinct types for these distinct concepts (even though both types have identical layout!). 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\_; // exposition only public: time\_point(); // has value "epoch" explicit time\_point(const duration& d); // same as time\_point() + d // conversions template \<class Duration2\> requires Convertible\<Duration2, duration\> time\_point(const time\_point\<clock, Duration2\>& t); // observer duration time\_since\_epoch() const; // arithmetic time\_point& operator+=(const duration& d); time\_point& operator-=(const duration& d); // special values static time\_point min(); static time\_point max(); }; } // datetime 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); // clocks // A clock specifies a representation, and a period. These specifications are used to // to define a clock's native duration and time\_point types. A clock also has a function to get the current // time\_point. A clock need not have any state. // The cost of not including separate types for clocks is that there is no better place to // bundle the "native" duration and time\_point types for a clock with the functionality to // get the current time\_point (what time is it now?). By bundling this information into a // type, the extension to support multiple clocks is both easy and obvious. The ability to // easily support multiple clocks in such a flexible yet simple and efficient manner is // very important. A client might (for example) write code with the clock as a generic // template parameter, and then easily experiment with different timers. class system\_clock { public: typedef \<unspecified\> rep; typedef ratio\<unspecified, unspecified\> period; typedef datetime::duration\<rep, period\> duration; typedef datetime::time\_point\ time\_point; static const bool is\_mononontic = \<unspecified\>; static time\_point now(); // Map to C API static time\_t to\_time\_t (const time\_point& t); static time\_point from\_time\_t(time\_t t); }; class monotonic\_clock // optional { 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 // optional { 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(); }; // Note: These clocks may be three separate types, or typedefs to one or two common types. } // datetime ////////////////////////// // Threading interface // ////////////////////////// // timed\_mutex 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; // optional. example: pthread\_mutex\_t\* native\_handle\_type native\_handle(); // optional }; // recursive\_timed\_mutex 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; // optional. example: pthread\_mutex\_t\* native\_handle\_type native\_handle(); // optional }; // unique\_lock 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(); }; // condition\_variable 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(); }; // condition\_variable\_any 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); }; // sleep 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); } // this\_thread } // std \*/#include <ctime>
#include <climits>
#include <inttypes.h>
#include <limits>
#include "type_traits"
#define decltype __typeof__
namespace std
{//////////////////////////////////////////////////////////////////////////////// common\_type /////////////////////////////////////////////////////////////////////////////////#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///////////////////////////////////////////////////////////////////////////////// ratio //////////////////////////////////////////////////////////////////////////////////////// \_\_static\_gcdtemplate <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;
};// \_\_static\_lcmtemplate <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];// static\_assert(X \<= max - Y, "overflow in \_\_ll\_add");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];// static\_assert(min - Y \<= X, "overflow in \_\_ll\_add");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];// static\_assert(min + Y \<= X, "overflow in \_\_ll\_sub");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];// static\_assert(X \<= max + Y, "overflow in \_\_ll\_sub");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];// static\_assert(X != nan && Y != nan && \_\_a\_x \<= max / \_\_a\_y, "overflow in \_\_ll\_mul");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;
};// Not actually used but left here in case needed in future maintenancetemplate <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];// static\_assert(X != nan && Y != nan && Y != 0, "overflow in \_\_ll\_div");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];// static\_assert(\_\_static\_abs\<N\>::value \>= 0, "ratio numerator is out of range");// static\_assert(D != 0, "ratio divide by 0");// static\_assert(\_\_static\_abs\<D\>::value \> 0, "ratio denominator is out of range");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;
};// ratio\_equaltemplate <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> {};// ratio\_less// Protect against overflow, and still get the right answer as much as possible.// This just demonstrates for fun how far you can push things without hitting// overflow. The obvious and simple implementation is conforming.template <class R1, class R2, bool ok1, bool ok2>
struct __ratio_less3// true, true and false, false{
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// N1 \< D1 == N2 \< D2{
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>// N1 \< D1 != N2 \< D2{
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// N1 \< D1 == N2 \< D2{
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>// N1 \< D1 != N2 \< D2{
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;
};//////////////////////////////////////////////////////////////////////////////// duration ////////////////////////////////////////////////////////////////////////////////////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> {};// duration\_cast// duration\_cast is the heart of this whole prototype. It can convert any// duration to any other. It is also (implicitly) used in converting// time\_points. The conversion is always exact if possible. And it is// always as efficient as hand written code. If different representations// are involved, care is taken to never require implicit conversions.// Instead static\_cast is used explicitly for every required conversion.// If there are a mixture of integral and floating point representations,// the use of common\_type ensures that the most logical "intermediate"// representation is used.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;// When the two periods are the same, all that is left to do is static\_cast from// the source representation to the target representation (which may be a no-op).// This conversion is always exact as long as the static\_cast from the source// representation to the destination representation is exact.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()));
}
};// When the numerator of FromPeriod / ToPeriod is 1, then all we need to do is// divide by the denominator of FromPeriod / ToPeriod. The common\_type of// the two representations is used for the intermediate computation before// static\_cast'ing to the destination.// This conversion is generally not exact because of the division (but could be// if you get lucky on the run time value of fd.count()).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)));
}
};// When the denomenator of FromPeriod / ToPeriod is 1, then all we need to do is// multiply by the numerator of FromPeriod / ToPeriod. The common\_type of// the two representations is used for the intermediate computation before// static\_cast'ing to the destination.// This conversion is always exact as long as the static\_cast's involved are exact.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)));
}
};// When neither the numerator or denominator of FromPeriod / ToPeriod is 1, then we need to// multiply by the numerator and divide by the denominator of FromPeriod / ToPeriod. The// common\_type of the two representations is used for the intermediate computation before// static\_cast'ing to the destination.// This conversion is generally not exact because of the division (but could be// if you get lucky on the run time value of fd.count()).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)));
}
};// Compile-time select the most efficient algorithm for the conversion...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);
}// Support bidirectional (non-exact) conversions for floating point rep types// (or user defined rep types which specialize treat\_as\_floating\_point).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>());}
};// durationtemplate <class Rep, class Period>
class duration
{
static char test0[!__is_duration<Rep>::value];// static\_assert(!\_\_is\_duration\<Rep\>::value, "A duration representation can not be a duration");static char test1[__is_ratio<Period>::value];// static\_assert(\_\_is\_ratio\<Period\>::value, "Second template parameter of duration must be a std::ratio");static char test2[Period::num > 0];// static\_assert(Period::num \> 0, "duration period must be positive");public:
typedef Rep rep;
typedef Period period;
private:
rep rep_;
public:
duration() {}// = default;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) {}// conversionstemplate <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()) {}// observerrep count() const {return rep_;}// arithmeticduration 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;}// special valuesstatic 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;
}// datetimetemplate <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 {// Duration ==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);
}// Duration !=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);
}// Duration \<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);
}// Duration \>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;
}// Duration \<=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);
}// Duration \>=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);
}// Duration +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;
}// Duration -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;
}// Duration \*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;
}// Duration /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();
}/////////////////////////////////////////////////////////////////////////////// time\_point ///////////////////////////////////////////////////////////////////////////////////template <class Clock, class Duration = typename Clock::duration>
class time_point
{
static char test1[__is_duration<Duration>::value];// static\_assert(\_\_is\_duration\<Duration\>::value,// "Second template parameter of time\_point must be a std::datetime::duration");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) {}// conversionstemplate <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()) {}// observerduration time_since_epoch() const {return d_;}// arithmetictime_point& operator+=(const duration& d) {d_ += d; return *this;}
time_point& operator-=(const duration& d) {d_ -= d; return *this;}// special valuesstatic time_point min() {return time_point(duration::min());}
static time_point max() {return time_point(duration::max());}
};
}// datetimetemplate <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()));
}// time\_point ==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();
}// time\_point !=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);
}// time\_point \<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();
}// time\_point \>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;
}// time\_point \<=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);
}// time\_point \>=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);
}// time\_point operator+(time\_point x, duration y);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;
}// time\_point operator+(duration x, time\_point y);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;
}// time\_point operator-(time\_point x, duration y);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);
}// duration operator-(time\_point x, time\_point y);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();
}///////////////////////////////////////////////////////////////////////////////// clocks /////////////////////////////////////////////////////////////////////////////////////// If you're porting, clocks are the system-specific (non-portable) part.// You'll need to know how to get the current time and implement that under now().// You'll need to know what units (tick period) and representation makes the most// sense for your clock and set those accordingly.// If you know how to map this clock to time\_t (perhaps your clock is std::time, which// makes that trivial), then you can fill out system\_clock's to\_time\_t() and from\_time\_t().class system_clock
{
public:
typedef microseconds duration;
typedef duration::rep rep;
typedef duration::period period;
typedef datetime::time_point 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;
}// datetime}// std// clocks.cpp#include <sys/time.h>//for gettimeofday and timeval#include <mach/mach_time.h>// mach\_absolute\_time, mach\_timebase\_info\_data\_tnamespace std {
namespace datetime {// system\_clock// gettimeofday is the most precise "system time" available on this platform.// It returns the number of microseconds since New Years 1970 in a struct called timeval// which has a field for seconds and a field for microseconds.// Fill in the timeval and then convert that to the time\_pointsystem_clock::time_point
system_clock::now()
{
timeval tv;
gettimeofday(&tv, 0);
return time_point(seconds(tv.tv_sec) + microseconds(tv.tv_usec));
}// Take advantage of the fact that on this platform time\_t is nothing but// an integral count of seconds since New Years 1970 (same epoch as timeval).// Just get the duration out of the time\_point and truncate it to seconds.time_t
system_clock::to_time_t(const time_point& t)
{
return time_t(duration_cast<seconds>(t.time_since_epoch()).count());
}// Just turn the time\_t into a count of seconds and construct a time\_point with it.system_clock::time_point
system_clock::from_time_t(time_t t)
{
return system_clock::time_point(seconds(t));
}// monotonic\_clock// Note, in this implementation monotonic\_clock and high\_resolution\_clock// are the same clock. They are both based on mach\_absolute\_time().// mach\_absolute\_time() \* MachInfo.numer / MachInfo.denom is the number of// nanoseconds since the computer booted up. MachInfo.numer and MachInfo.denom// are run time constants supplied by the OS. This clock has no relationship// to the Gregorian calendar. It's main use is as a high resolution timer.// MachInfo.numer / MachInfo.denom is often 1 on the latest equipment. Specialize// for that case as an optimization.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()));
}// clocks.cpp end} }// std::datetime/////////////////////////////////////////////////////////////////////// simulated thread interface ///////////////////////////////////////////////////////////////////////////#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;/\* auto \*/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";
}
}
}// this\_threadstruct 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;/\* auto \*/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;/\* auto \*/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";
}
};
}// std///////////////////////////////////////////////////////////////////////////// End of implemetation //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// Simple sleep and wait examples ////////////////////////////////////////////////////////////////////////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);// this\_thread::sleep\_for(time\_limit); // desired compile-time error// this\_thread::sleep\_until(seconds(3)); // desired compile-time errormut.try_lock_for(milliseconds(30));
mut.try_lock_until(time_limit);// mut.try\_lock\_for(time\_limit); // desired compile-time error// mut.try\_lock\_until(milliseconds(30)); // desired compile-time errorcv.wait_for(m, minutes(1));// real code would put this in a loopcv.wait_until(m, time_limit);// real code would put this in a loop// For those who prefer floating pointthis_thread::sleep_for(duration<double>(0.25));
this_thread::sleep_until(system_clock::now() + duration<double>(1.5));
}////////////////////////////////////////////////////////////////////////////// User1 Example /////////////////////////////////////////////////////////////////////////////////namespace User1
{// Example type-safe "physics" code interoperating with std::datetime::duration types// and taking advantage of the std::ratio infrastructure and design philosophy.// length - mimics std::datetime::duration except restricts representation to double.// Uses std::ratio facilities for length units conversions.template <class Ratio>
class length
{
public:
typedef Ratio ratio;
private:
double len_;
public:
length() : len_(1) {}
length(const double& len) : len_(len) {}// conversionstemplate <class R>
length(const length<R>& d)
: len_(d.count() * std::ratio_divide<Ratio, R>::type::den /
std::ratio_divide<Ratio, R>::type::num) {}// observerdouble count() const {return len_;}// arithmeticlength& 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;}
};// Sparse sampling of length unitstypedef length<std::ratio<1> > meter;// set meter as "unity"typedef length<std::centi> centimeter;// 1/100 metertypedef length<std::kilo> kilometer;// 1000 meterstypedef length<std::ratio<254, 10000> > inch;// 254/10000 meters// length takes ratio instead of two integral types so that definitions can be made like so:typedef length<std::ratio_multiply<std::ratio<12>, inch::ratio>::type> foot;// 12 inchstypedef length<std::ratio_multiply<std::ratio<5280>, foot::ratio>::type> mile;// 5280 feet// Need a floating point definition of secondstypedef std::datetime::duration<double> seconds;// unity// Demo of (scientific) support for sub-nanosecond resolutionstypedef std::datetime::duration<double, std::pico> picosecond;// 10^-12 secondstypedef std::datetime::duration<double, std::femto> femtosecond;// 10^-15 secondstypedef std::datetime::duration<double, std::atto> attosecond;// 10^-18 seconds// A very brief proof-of-concept for SIUnits-like library// Hard-wired to floating point seconds and meters, but accepts other units (shown in testUser1())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()) {}// note: only User1::seconds needed heredouble 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()) {}// note: only User1::meter needed heredouble 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;}
};// Example SI-Unitstypedef quantity<std::ratio<0>, std::ratio<0> > Scalar;
typedef quantity<std::ratio<1>, std::ratio<0> > Time;// secondtypedef quantity<std::ratio<0>, std::ratio<1> > Distance;// metertypedef quantity<std::ratio<-1>, std::ratio<1> > Speed;// meter/secondtypedef quantity<std::ratio<-2>, std::ratio<1> > Acceleration;// meter/second^2template <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;
}// Example type-safe physics functionDistance
compute_distance(Speed v0, Time t, Acceleration a)
{
return v0 * t + Scalar(.5) * a * t * t;// if a units mistake is made here it won't compile}
}// User1#include <iostream>// Exercise example type-safe physics function and show interoperation// of custom time durations (User1::seconds) and standard time durations (std::hours).// Though input can be arbitrary (but type-safe) units, output is always in SI-units// (a limitation of the simplified Units lib demoed here).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;// compiles\n";sec = User1::seconds(1);
as = sec;
std::cout << "1 second is " << as.count() << " attoseconds\n";
std::cout << "as = sec;// compiles\n";std::cout << "\n";
}////////////////////////////////////////////////////////////////////////////// User2 Example /////////////////////////////////////////////////////////////////////////////////// Demonstrate User2:// A "saturating" signed integral type is developed. This type has +/- infinity and a nan// (like IEEE floating point) but otherwise obeys signed integral arithmetic.// This class is subsequently used as the rep in std::datetime::duration to demonstrate a// duration class that does not silently ignore overflow.#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_;// static\_assert(std::is\_integral\<int\_type\>::value && std::is\_signed\<int\_type\>::value,// "saturate only accepts signed integral types");// static\_assert(nan == -nan && neg\_inf \< pos\_inf,// "saturate assumes two's complement hardware for signed integrals");public:
saturate() : i_(nan) {}
explicit saturate(int_type i) : i_(i) {}// explicitoperator 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)
{// \*this -= \*this / x \* x; // definitionswitch (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;
}// Demo overflow-safe integral durations ranging from picoseconds resolution to millennium resolutiontypedef 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;
}// User2// Demonstrate custom promotion rules (needed only if there are no implicit conversions)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>// integral{
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>// floating{
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> > {};// Demonstrate specialization of duration\_values: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';// yr = ns; // does not compilestd::cout << "yr = ns;// does not compile\n";// picoseconds ps1 = yr; // does not compile, compile-time overflow in ratio arithmeticstd::cout << "ps = yr;// does not compile\n";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';// hr = ns; // does not compilestd::cout << "hr = ns;// does not compile\n";// hr \* ns; // does not compilestd::cout << "hr * ns;// does not compile\n";duration<double> fs(2.5);
std::cout << "duration<double> has count() = " << fs.count() << '\n';// seconds sec = fs; // does not compilestd::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";
}// timeval clock demo// Demonstrate the use of a timeval-like struct to be used as the representation// type for both duraiton and time\_point.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();
}// explicitoperator 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";
}
}// timeval\_demo// Handle duration with resolution not known until run timenamespace 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() {}// = default;explicit duration(const rep& r) : rep_(r) {}// conversionsexplicit duration(const tonanosec& d)
: rep_(static_cast<rep>(d.count() * ticks_per_nanosecond)) {}// explicitoperator tonanosec() const {return tonanosec(rep_/ticks_per_nanosecond);}// observerrep count() const {return rep_;}// arithmeticduration& 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()) {}// arithmetictime_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";
}
}// runtime\_resolution// miscellaneous tests and demos:#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));/\*auto\*/microseconds u1 = h1 + microseconds(1);/\*auto\*/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;// Example round\_up utility: converts d to To, rounding up for inexact conversions// Being able to \*easily\* write this function is a major feature!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;
}// demonstrate interaction with xtime-like facility: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";// mend - sstart; // doesn't compilecout << "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(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
{// Here's how you override the duration's default constructor to do anything you want (in this case zero)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';
}
}// I\_dont\_like\_the\_default\_duration\_behavior// Build a min for two time\_pointstemplate <class Rep, class Period>
void
print_duration(ostream& os, duration<Rep, Period> d)
{
os << d.count() << " * " << Period::num << '/' << Period::den << " seconds\n";
}// Example min utility: returns the earliest time\_point// Being able to \*easily\* write this function is a major feature!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::type> T1;
typedef time_point::type> T2;
typedef common_type<T1, T2>::type T3;/\*auto\*/T1 t1 = system_clock::now() + seconds(3);/\*auto\*/T2 t2 = system_clock::now() + nanoseconds(3);/\*auto\*/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));// nanosecond resolution is likely to overflow. "up cast" to microseconds.// The "up cast" trades precision for range.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;// Mhztypedef 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;// return exact cycle countreturn time_point(duration(++tick));// fake access to clock cycle count}
};
template <long long speed>
struct approx_cycle_count
{
static const long long frequency = speed * 1000000;// MHztypedef 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;// return cycle count as an approximate number of nanoseconds// compute as if nanoseconds is only duration in the std::libreturn 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)// no multiplies or divides in this loop;
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)// 1 multiplication and 1 division in this loop;
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)// no multiplies or divides in this loop;
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)// 1 multiplication and 1 division in this loop;
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';// milliseconds ms(3.5); // doesn't compilecout << "milliseconds ms(3.5) doesn't compile\n";
cycle_count_delay();
test_special_values();
}/\* 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; // does not compile hr \* ns; // does not compile 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; // compiles 1 second is 1e+18 attoseconds as = sec; // compiles \*\*\*\*\*\*\*\*\*\*\*\*\* \* 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; // does not compile ps = yr; // does not compile 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 \*//\* 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 \*/