/* * Copyright (c) 2017 Jaroslav Jindrak * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef LIBCPP_CHRONO #define LIBCPP_CHRONO #include #include #include #include namespace std::chrono { /** * 20.12.5, class template duration: */ // Forward declarations. template> class duration; template constexpr ToDuration duration_cast(const duration& dur); template struct duration_values; template class duration { public: using rep = Rep; using period = Period; /** * 20.12.5.1, construct/copy/destroy: */ constexpr duration() = default; // TODO: check remarks to these two constructors, need is_convertible template constexpr explicit duration(const Rep2& r) : rep_{r} { /* DUMMY BODY */ } template constexpr duration(const duration& other) : rep_{duration_cast(other).count()} { /* DUMMY BODY */ } ~duration() = default; duration(const duration&) = default; duration& operator=(const duration&) = default; /** * 20.12.5.2, observer: */ constexpr rep count() const { return rep_; } /** * 20.12.5.3, arithmetic: */ constexpr duration operator+() const { return *this; } constexpr duration operator-() const { return duration{-rep_}; } duration& operator++() { ++rep_; return *this; } duration operator++(int) { return duration{rep_++}; } duration& operator--() { --rep_; *this; } duration operator--(int) { return duration{rep_--}; } duration& operator+=(const duration& rhs) { rep_ += rhs.count(); return *this; } duration& operator-=(const duration& rhs) { rep_ -= rhs.count(); return *this; } duration& operator*=(const rep& rhs) { rep_ *= rhs; return *this; } duration& operator/=(const rep& rhs) { rep_ /= rhs; return *this; } duration& operator%=(const rep& rhs) { rep_ %= rhs; return *this; } duration& operator%=(const duration& rhs) { rep_ %= rhs.count(); return *this; } /** * 20.12.5.4, special values: */ static constexpr duration zero() { return duration{duration_values::zero()}; } static constexpr duration min() { return duration{duration_values::min()}; } static constexpr duration max() { return duration{duration_values::max()}; } private: rep rep_; }; /** * 20.12.6, class template time_point: */ template class time_point { public: using clock = Clock; using duration = Duration; using rep = typename duration::rep; using period = typename duration::period; /** * 20.12.6.1, construct: */ constexpr time_point() : duration_{duration::zero()} { /* DUMMY BODY */ } constexpr explicit time_point(const duration& d) : duration_{d} { /* DUMMY BODY */ } // TODO: see remark to this constuctor template constexpr time_point(const time_point& other) : duration_{static_cast(other.time_since_epoch())} { /* DUMMY BODY */ } /** * 20.12.6.2, observer: */ constexpr duration time_since_epoch() const { return duration_; } /** * 20.12.6.3, arithmetic: */ time_point& operator+=(const duration& rhs) { duration_ += rhs; return *this; } time_point& operator-=(const duration& rhs) { duration_ -= rhs; return *this; } /** * 20.12.6.4, special values: */ static constexpr time_point min() { return time_point{duration::min()}; } static constexpr time_point max() { return time_point{duration::max()}; } private: duration duration_; }; } namespace std { /** * 20.12.4.3, common_type specializations: */ template struct common_type, chrono::duration> { using type = chrono::duration< common_type_t, ratio, aux::lcm_v> >; }; template struct common_type, chrono::time_point> { using type = chrono::time_point>; }; } namespace std::chrono { /** * 20.12.4, customization traits: */ template struct treat_as_floating_point: is_floating_point { /* DUMMY BODY */ }; template struct duration_values { static constexpr Rep zero() { // Note: Using Rep(0) instead of Rep{} is intentional, do not change. return Rep(0); } static constexpr Rep min() { return numeric_limits::lowest(); } static constexpr Rep max() { return numeric_limits::max(); } }; /** * 20.12.5.5, duration arithmetic: */ template constexpr common_type_t, duration> operator+(const duration& lhs, const duration& rhs) { using CD = common_type_t, duration>; return CD(CD(lhs.count()) + CD(rhs.count())); } template constexpr common_type_t, duration> operator-(const duration& lhs, const duration& rhs) { using CD = common_type_t, duration>; return CD(CD(lhs).count() - CD(rhs).count()); } // TODO: This shall not participate in overloading if Rep2 is not implicitly // convertible to CR(Rep1, Rep2) -> CR(A, B) defined in standard as // common_type_t. template constexpr duration, Period> operator*(const duration& dur, const Rep2& rep) { using CD = duration, Period>; return CD(CD(dur).count() * rep); } // TODO: This shall not participate in overloading if Rep2 is not implicitly // convertible to CR(Rep1, Rep2) -> CR(A, B) defined in standard as // common_type_t. template constexpr duration, Period> operator*(const Rep2& rep, const duration& dur) { return dur * rep; } // TODO: This shall not participate in overloading if Rep2 is not implicitly // convertible to CR(Rep1, Rep2) -> CR(A, B) defined in standard as // common_type_t. template constexpr duration, Period> operator/(const duration& dur, const Rep2& rep) { using CD = duration, Period>; return CD(CD(dur).count() / rep); } template constexpr common_type_t operator/(const duration& lhs, const duration& rhs) { using CD = common_type_t; return CD(lhs).count() / CD(rhs).count(); } // TODO: This shall not participate in overloading if Rep2 is not implicitly // convertible to CR(Rep1, Rep2) -> CR(A, B) defined in standard as // common_type_t. template constexpr duration, Period> operator%(const duration& dur, const Rep2& rep) { using CD = duration, Period>; return CD(CD(dur).count() / rep); } template constexpr common_type_t, duration> operator%(const duration& lhs, const duration& rhs) { using CD = common_type_t, duration>; return CD(CD(lhs).count() % CD(rhs).count()); } /** * 20.12.5.6, duration comparisons: */ template constexpr bool operator==(const duration& lhs, const duration& rhs) { using CT = common_type_t, duration>; return CT(lhs).count() == CT(rhs).count(); } template constexpr bool operator!=(const duration& lhs, const duration& rhs) { return !(lhs == rhs); } template constexpr bool operator<(const duration& lhs, const duration& rhs) { using CT = common_type_t, duration>; return CT(lhs).count() < CT(rhs).count(); } template constexpr bool operator<=(const duration& lhs, const duration& rhs) { return !(rhs < lhs); } template constexpr bool operator>(const duration& lhs, const duration& rhs) { return rhs < lhs; } template constexpr bool operator>=(const duration& lhs, const duration& rhs) { return !(lhs < rhs); } /** * 20.12.5.7, duration cast: */ // TODO: This function should not participate in overloading // unless ToDuration is an instantiation of duration. template constexpr ToDuration duration_cast(const duration& dur) { using CF = ratio_divide; using CR = typename common_type::type; using to_rep = typename ToDuration::rep; if constexpr (CF::num == 1 && CF::den == 1) return ToDuration(static_cast(dur.count())); else if constexpr (CF::num != 1 && CF::den == 1) { return ToDuration( static_cast( static_cast(dur.count()) * static_cast(CF::num) ) ); } else if constexpr (CF::num == 1 && CF::den != 1) { return ToDuration( static_cast( static_cast(dur.count()) / static_cast(CF::den) ) ); } else { return ToDuration( static_cast( static_cast(dur.count()) * static_cast(CF::num) / static_cast(CF::den) ) ); } } // convenience typedefs using nanoseconds = duration; using microseconds = duration; using milliseconds = duration; using seconds = duration; using minutes = duration>; using hours = duration>; /** * 20.12.6.5, time_point arithmetic: */ template constexpr time_point>> operator+(const time_point& lhs, const duration& rhs) { using CT = time_point>>; return CT(lhs.time_since_epoch() + rhs); } template constexpr time_point, Duration2>> operator+(const duration& lhs, const time_point& rhs) { return rhs + lhs; } template constexpr time_point>> operator-(const time_point& lhs, const duration& rhs) { return lhs + (-rhs); } template constexpr common_type_t operator-(const time_point& lhs, const time_point& rhs) { return lhs.time_since_epoch() - rhs.time_since_epoch(); } /** * 20.12.6.6, time_point comparisons: */ template constexpr bool operator==(const time_point& lhs, const time_point& rhs) { return lhs.time_since_epoch() == rhs.time_since_epoch(); } template constexpr bool operator!=(const time_point& lhs, const time_point& rhs) { return !(lhs == rhs); } template constexpr bool operator<(const time_point& lhs, const time_point& rhs) { return lhs.time_since_epoch() < rhs.time_since_epoch(); } template constexpr bool operator<=(const time_point& lhs, const time_point& rhs) { return !(rhs < lhs); } template constexpr bool operator>(const time_point& lhs, const time_point& rhs) { return rhs < lhs; } template constexpr bool operator>=(const time_point& lhs, const time_point& rhs) { return !(lhs < rhs); } /** * 20.12.6.7, time_point cast: */ // TODO: This function should not participate in overloading // unless ToDuration is an instantiation of duration. template constexpr time_point time_point_cast(const time_point& tp) { return time_point( duration_cast(tp.time_since_epoch()) ); } /** * 20.12.7, clocks: */ class system_clock { public: using rep = int64_t; using period = micro; using duration = chrono::duration; using time_point = chrono::time_point; // TODO: is it steady? static constexpr bool is_steady = true; static time_point now() { hel::timeval tv{}; hel::gettimeofday(&tv, nullptr); rep time = tv.tv_usec; time += (tv.tv_sec * 1'000'000ul); return time_point{duration{time - epoch_usecs}}; } static time_t to_time_t(const time_point& tp) { /* auto dur = tp.time_since_epoch(); */ /* auto time_t_dur = duration_cast>(dur); */ /* return time_t{time_t_dur.count()}; */ return time_t{}; } static time_point from_time_t(time_t tt) { /* auto time_t_dur = chrono::duration{tt}; */ /* auto dur = duration_cast(time_t_dur); */ /* return time_point{duration_cast(chrono::duration{tt})}; */ return time_point{}; } private: static constexpr rep epoch_usecs{11644473600ul * 1'000'000ul}; }; class steady_clock { public: using rep = int64_t; using period = micro; using duration = chrono::duration; using time_point = chrono::time_point; static constexpr bool is_steady = true; static time_point now() { hel::timeval tv{}; hel::getuptime(&tv); rep time = tv.tv_usec; time += (tv.tv_sec * 1'000'000ul); return time_point{duration{time}}; } }; using high_resolution_clock = system_clock; } namespace std { inline namespace literals { inline namespace chrono_literals { /** * 20.125.8, suffixes for duration literals: */ /** * Note: According to the standard, literal suffixes that do not * start with an underscore are reserved for future standardization, * but since we are implementing the standard, we're going to ignore it. * This should work (according to their documentation) work for clang, * but that should be tested. */ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wliteral-suffix" constexpr chrono::hours operator ""h(unsigned long long hrs) { return chrono::hours{static_cast(hrs)}; } constexpr chrono::duration> operator ""h(long double hrs) { return chrono::duration>{hrs}; } constexpr chrono::minutes operator ""m(unsigned long long mins) { return chrono::minutes{static_cast(mins)}; } constexpr chrono::duration> operator ""m(long double mins) { return chrono::duration>{mins}; } constexpr chrono::seconds operator ""s(unsigned long long secs) { return chrono::seconds{static_cast(secs)}; } constexpr chrono::duration> operator ""s(long double secs) { return chrono::duration>{secs}; } constexpr chrono::milliseconds operator ""ms(unsigned long long msecs) { return chrono::milliseconds{static_cast(msecs)}; } constexpr chrono::duration operator ""ms(long double msecs) { return chrono::duration{msecs}; } constexpr chrono::microseconds operator ""us(unsigned long long usecs) { return chrono::microseconds{static_cast(usecs)}; } constexpr chrono::duration operator ""us(long double usecs) { return chrono::duration{usecs}; } constexpr chrono::nanoseconds operator ""ns(unsigned long long nsecs) { return chrono::nanoseconds{static_cast(nsecs)}; } constexpr chrono::duration operator ""ns(long double nsecs) { return chrono::duration{nsecs}; } #pragma GCC diagnostic pop } } namespace chrono { using namespace literals::chrono_literals; } } #endif