// chrono standard header // Copyright (c) Microsoft Corporation. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception #pragma once #ifndef _CHRONO_ #define _CHRONO_ #include #if _STL_COMPILER_PREPROCESSOR #include #include #include #include #include #include #pragma pack(push, _CRT_PACKING) #pragma warning(push, _STL_WARNING_LEVEL) #pragma warning(disable : _STL_DISABLED_WARNINGS) _STL_DISABLE_CLANG_WARNINGS #pragma push_macro("new") #undef new _STD_BEGIN namespace chrono { // STRUCT TEMPLATE treat_as_floating_point template struct treat_as_floating_point : is_floating_point<_Rep> { // tests for floating-point type }; template _INLINE_VAR constexpr bool treat_as_floating_point_v = treat_as_floating_point<_Rep>::value; // STRUCT TEMPLATE duration_values template struct duration_values { // gets arithmetic properties of a type _NODISCARD static constexpr _Rep zero() noexcept { // get zero value return _Rep(0); } _NODISCARD static constexpr _Rep(min)() noexcept { // get smallest value return numeric_limits<_Rep>::lowest(); } _NODISCARD static constexpr _Rep(max)() noexcept { // get largest value return (numeric_limits<_Rep>::max)(); } }; // CLASS TEMPLATE duration template > class duration; // VARIABLE TEMPLATE _Is_duration_v template _INLINE_VAR constexpr bool _Is_duration_v = _Is_specialization_v<_Ty, duration>; template , int> = 0> constexpr _To duration_cast(const duration<_Rep, _Period>&) noexcept( is_arithmetic_v<_Rep>&& is_arithmetic_v); // strengthened template class duration { // represents a time duration public: using rep = _Rep; using period = typename _Period::type; static_assert(!_Is_duration_v<_Rep>, "duration can't have duration as first template argument"); static_assert(_Is_ratio_v<_Period>, "period not an instance of std::ratio"); static_assert(0 < _Period::num, "period negative or zero"); constexpr duration() = default; template && (treat_as_floating_point_v<_Rep> || !treat_as_floating_point_v<_Rep2>), int> = 0> constexpr explicit duration(const _Rep2& _Val) noexcept( is_arithmetic_v<_Rep>&& is_arithmetic_v<_Rep2>) // strengthened : _MyRep(static_cast<_Rep>(_Val)) {} template || (_Ratio_divide_sfinae<_Period2, _Period>::den == 1 && !treat_as_floating_point_v<_Rep2>), int> = 0> constexpr duration(const duration<_Rep2, _Period2>& _Dur) noexcept( is_arithmetic_v<_Rep>&& is_arithmetic_v<_Rep2>) // strengthened : _MyRep(chrono::duration_cast(_Dur).count()) {} _NODISCARD constexpr _Rep count() const noexcept(is_arithmetic_v<_Rep>) /* strengthened */ { return _MyRep; } _NODISCARD constexpr common_type_t operator+() const noexcept(is_arithmetic_v<_Rep>) /* strengthened */ { return common_type_t(*this); } _NODISCARD constexpr common_type_t operator-() const noexcept(is_arithmetic_v<_Rep>) /* strengthened */ { return common_type_t(-_MyRep); } _CONSTEXPR17 duration& operator++() noexcept(is_arithmetic_v<_Rep>) /* strengthened */ { ++_MyRep; return *this; } _CONSTEXPR17 duration operator++(int) noexcept(is_arithmetic_v<_Rep>) /* strengthened */ { return duration(_MyRep++); } _CONSTEXPR17 duration& operator--() noexcept(is_arithmetic_v<_Rep>) /* strengthened */ { --_MyRep; return *this; } _CONSTEXPR17 duration operator--(int) noexcept(is_arithmetic_v<_Rep>) /* strengthened */ { return duration(_MyRep--); } _CONSTEXPR17 duration& operator+=(const duration& _Right) noexcept(is_arithmetic_v<_Rep>) /* strengthened */ { _MyRep += _Right._MyRep; return *this; } _CONSTEXPR17 duration& operator-=(const duration& _Right) noexcept(is_arithmetic_v<_Rep>) /* strengthened */ { _MyRep -= _Right._MyRep; return *this; } _CONSTEXPR17 duration& operator*=(const _Rep& _Right) noexcept(is_arithmetic_v<_Rep>) /* strengthened */ { _MyRep *= _Right; return *this; } _CONSTEXPR17 duration& operator/=(const _Rep& _Right) noexcept(is_arithmetic_v<_Rep>) /* strengthened */ { _MyRep /= _Right; return *this; } _CONSTEXPR17 duration& operator%=(const _Rep& _Right) noexcept(is_arithmetic_v<_Rep>) /* strengthened */ { _MyRep %= _Right; return *this; } _CONSTEXPR17 duration& operator%=(const duration& _Right) noexcept(is_arithmetic_v<_Rep>) /* strengthened */ { _MyRep %= _Right.count(); return *this; } _NODISCARD static constexpr duration zero() noexcept { // get zero value return duration(duration_values<_Rep>::zero()); } _NODISCARD static constexpr duration(min)() noexcept { // get minimum value return duration((duration_values<_Rep>::min)()); } _NODISCARD static constexpr duration(max)() noexcept { // get maximum value return duration((duration_values<_Rep>::max)()); } private: _Rep _MyRep; // the stored rep }; template class time_point { // represents a point in time public: using clock = _Clock; using duration = _Duration; using rep = typename _Duration::rep; using period = typename _Duration::period; static_assert(_Is_duration_v<_Duration>, "duration must be an instance of std::duration"); constexpr time_point() = default; constexpr explicit time_point(const _Duration& _Other) noexcept(is_arithmetic_v) // strengthened : _MyDur(_Other) {} template , int> = 0> constexpr time_point(const time_point<_Clock, _Duration2>& _Tp) noexcept( is_arithmetic_v&& is_arithmetic_v) // strengthened : _MyDur(_Tp.time_since_epoch()) {} _NODISCARD constexpr _Duration time_since_epoch() const noexcept(is_arithmetic_v) /* strengthened */ { return _MyDur; } _CONSTEXPR17 time_point& operator+=(const _Duration& _Dur) noexcept(is_arithmetic_v) /* strengthened */ { _MyDur += _Dur; return *this; } _CONSTEXPR17 time_point& operator-=(const _Duration& _Dur) noexcept(is_arithmetic_v) /* strengthened */ { _MyDur -= _Dur; return *this; } _NODISCARD static constexpr time_point(min)() noexcept { return time_point((_Duration::min)()); } _NODISCARD static constexpr time_point(max)() noexcept { return time_point((_Duration::max)()); } private: _Duration _MyDur{duration::zero()}; // duration since the epoch }; } // namespace chrono // STRUCT TEMPLATE _Lcm (LEAST COMMON MULTIPLE) template struct _Lcm : integral_constant::value) * _Bx> { // compute least common multiple of _Ax and _Bx }; // STRUCT TEMPLATE common_type SPECIALIZATIONS template struct common_type, chrono::duration<_Rep2, _Period2>> { // common type of two durations using type = chrono::duration, ratio<_Gcd<_Period1::num, _Period2::num>::value, _Lcm<_Period1::den, _Period2::den>::value>>; }; template struct common_type, chrono::time_point<_Clock, _Duration2>> { // common type of two time points using type = chrono::time_point<_Clock, common_type_t<_Duration1, _Duration2>>; }; namespace chrono { // duration ARITHMETIC template _NODISCARD constexpr common_type_t, duration<_Rep2, _Period2>> operator+(const duration<_Rep1, _Period1>& _Left, const duration<_Rep2, _Period2>& _Right) noexcept( is_arithmetic_v<_Rep1>&& is_arithmetic_v<_Rep2>) /* strengthened */ { using _CD = common_type_t, duration<_Rep2, _Period2>>; return _CD(_CD(_Left).count() + _CD(_Right).count()); } template _NODISCARD constexpr common_type_t, duration<_Rep2, _Period2>> operator-(const duration<_Rep1, _Period1>& _Left, const duration<_Rep2, _Period2>& _Right) noexcept( is_arithmetic_v<_Rep1>&& is_arithmetic_v<_Rep2>) /* strengthened */ { using _CD = common_type_t, duration<_Rep2, _Period2>>; return _CD(_CD(_Left).count() - _CD(_Right).count()); } template >, int> = 0> _NODISCARD constexpr duration, _Period1> operator*( const duration<_Rep1, _Period1>& _Left, const _Rep2& _Right) noexcept(is_arithmetic_v<_Rep1>&& is_arithmetic_v<_Rep2>) /* strengthened */ { using _CR = common_type_t<_Rep1, _Rep2>; using _CD = duration<_CR, _Period1>; return _CD(_CD(_Left).count() * _Right); } template >, int> = 0> _NODISCARD constexpr duration, _Period2> operator*(const _Rep1& _Left, const duration<_Rep2, _Period2>& _Right) noexcept( is_arithmetic_v<_Rep1>&& is_arithmetic_v<_Rep2>) /* strengthened */ { return _Right * _Left; } template > struct _Duration_div_mod1 { // return type for duration / rep and duration % rep using type = duration<_CR, _Period1>; }; template struct _Duration_div_mod1<_CR, _Period1, _Rep2, false> { // no return type }; template > struct _Duration_div_mod { // no return type }; template struct _Duration_div_mod<_CR, _Period1, _Rep2, false> : _Duration_div_mod1<_CR, _Period1, _Rep2> { // return type for duration / rep and duration % rep }; template _NODISCARD constexpr typename _Duration_div_mod, _Period1, _Rep2>::type operator/( const duration<_Rep1, _Period1>& _Left, const _Rep2& _Right) noexcept(is_arithmetic_v<_Rep1>&& is_arithmetic_v<_Rep2>) /* strengthened */ { using _CR = common_type_t<_Rep1, _Rep2>; using _CD = duration<_CR, _Period1>; return _CD(_CD(_Left).count() / _Right); } template _NODISCARD constexpr common_type_t<_Rep1, _Rep2> operator/(const duration<_Rep1, _Period1>& _Left, const duration<_Rep2, _Period2>& _Right) noexcept( is_arithmetic_v<_Rep1>&& is_arithmetic_v<_Rep2>) /* strengthened */ { using _CD = common_type_t, duration<_Rep2, _Period2>>; return _CD(_Left).count() / _CD(_Right).count(); } template _NODISCARD constexpr typename _Duration_div_mod, _Period1, _Rep2>::type operator%( const duration<_Rep1, _Period1>& _Left, const _Rep2& _Right) noexcept(is_arithmetic_v<_Rep1>&& is_arithmetic_v<_Rep2>) /* strengthened */ { using _CR = common_type_t<_Rep1, _Rep2>; using _CD = duration<_CR, _Period1>; return _CD(_CD(_Left).count() % _Right); } template _NODISCARD constexpr common_type_t, duration<_Rep2, _Period2>> operator%(const duration<_Rep1, _Period1>& _Left, const duration<_Rep2, _Period2>& _Right) noexcept( is_arithmetic_v<_Rep1>&& is_arithmetic_v<_Rep2>) /* strengthened */ { using _CD = common_type_t, duration<_Rep2, _Period2>>; return _CD(_CD(_Left).count() % _CD(_Right).count()); } // duration COMPARISONS template _NODISCARD constexpr bool operator==(const duration<_Rep1, _Period1>& _Left, const duration<_Rep2, _Period2>& _Right) noexcept( is_arithmetic_v<_Rep1>&& is_arithmetic_v<_Rep2>) /* strengthened */ { using _CT = common_type_t, duration<_Rep2, _Period2>>; return _CT(_Left).count() == _CT(_Right).count(); } template _NODISCARD constexpr bool operator!=(const duration<_Rep1, _Period1>& _Left, const duration<_Rep2, _Period2>& _Right) noexcept( is_arithmetic_v<_Rep1>&& is_arithmetic_v<_Rep2>) /* strengthened */ { return !(_Left == _Right); } template _NODISCARD constexpr bool operator<(const duration<_Rep1, _Period1>& _Left, const duration<_Rep2, _Period2>& _Right) noexcept( is_arithmetic_v<_Rep1>&& is_arithmetic_v<_Rep2>) /* strengthened */ { using _CT = common_type_t, duration<_Rep2, _Period2>>; return _CT(_Left).count() < _CT(_Right).count(); } template _NODISCARD constexpr bool operator<=(const duration<_Rep1, _Period1>& _Left, const duration<_Rep2, _Period2>& _Right) noexcept( is_arithmetic_v<_Rep1>&& is_arithmetic_v<_Rep2>) /* strengthened */ { return !(_Right < _Left); } template _NODISCARD constexpr bool operator>(const duration<_Rep1, _Period1>& _Left, const duration<_Rep2, _Period2>& _Right) noexcept( is_arithmetic_v<_Rep1>&& is_arithmetic_v<_Rep2>) /* strengthened */ { return _Right < _Left; } template _NODISCARD constexpr bool operator>=(const duration<_Rep1, _Period1>& _Left, const duration<_Rep2, _Period2>& _Right) noexcept( is_arithmetic_v<_Rep1>&& is_arithmetic_v<_Rep2>) /* strengthened */ { return !(_Left < _Right); } // FUNCTION TEMPLATE duration_cast template , int> _Enabled> _NODISCARD constexpr _To duration_cast(const duration<_Rep, _Period>& _Dur) noexcept( is_arithmetic_v<_Rep>&& is_arithmetic_v) /* strengthened */ { // convert duration to another duration; truncate using _CF = ratio_divide<_Period, typename _To::period>; using _ToRep = typename _To::rep; using _CR = common_type_t<_ToRep, _Rep, intmax_t>; constexpr bool _Num_is_one = _CF::num == 1; constexpr bool _Den_is_one = _CF::den == 1; if (_Den_is_one) { if (_Num_is_one) { return static_cast<_To>(static_cast<_ToRep>(_Dur.count())); } else { return static_cast<_To>( static_cast<_ToRep>(static_cast<_CR>(_Dur.count()) * static_cast<_CR>(_CF::num))); } } else { if (_Num_is_one) { return static_cast<_To>( static_cast<_ToRep>(static_cast<_CR>(_Dur.count()) / static_cast<_CR>(_CF::den))); } else { return static_cast<_To>(static_cast<_ToRep>( static_cast<_CR>(_Dur.count()) * static_cast<_CR>(_CF::num) / static_cast<_CR>(_CF::den))); } } } // FUNCTION TEMPLATE floor template , int> = 0> _NODISCARD constexpr _To floor(const duration<_Rep, _Period>& _Dur) noexcept( is_arithmetic_v<_Rep>&& is_arithmetic_v) /* strengthened */ { // convert duration to another duration; round towards negative infinity // i.e. the greatest integral result such that the result <= _Dur const _To _Casted{chrono::duration_cast<_To>(_Dur)}; if (_Casted > _Dur) { return _To{_Casted.count() - static_cast(1)}; } return _Casted; } // FUNCTION TEMPLATE ceil template , int> = 0> _NODISCARD constexpr _To ceil(const duration<_Rep, _Period>& _Dur) noexcept( is_arithmetic_v<_Rep>&& is_arithmetic_v) /* strengthened */ { // convert duration to another duration; round towards positive infinity // i.e. the least integral result such that _Dur <= the result const _To _Casted{chrono::duration_cast<_To>(_Dur)}; if (_Casted < _Dur) { return _To{_Casted.count() + static_cast(1)}; } return _Casted; } // FUNCTION TEMPLATE round template constexpr bool _Is_even(_Rep _Val) noexcept(is_arithmetic_v<_Rep>) /* strengthened */ { // Tests whether _Val is even return _Val % 2 == 0; } template && !treat_as_floating_point_v, int> = 0> _NODISCARD constexpr _To round(const duration<_Rep, _Period>& _Dur) noexcept( is_arithmetic_v<_Rep>&& is_arithmetic_v) /* strengthened */ { // convert duration to another duration, round to nearest, ties to even const _To _Floored{chrono::floor<_To>(_Dur)}; const _To _Ceiled{_Floored + _To{1}}; const auto _Floor_adjustment = _Dur - _Floored; const auto _Ceil_adjustment = _Ceiled - _Dur; if (_Floor_adjustment < _Ceil_adjustment || (_Floor_adjustment == _Ceil_adjustment && _Is_even(_Floored.count()))) { return _Floored; } return _Ceiled; } // FUNCTION TEMPLATE abs template ::is_signed, int> = 0> _NODISCARD constexpr duration<_Rep, _Period> abs(const duration<_Rep, _Period> _Dur) noexcept( is_arithmetic_v<_Rep>) /* strengthened */ { // create a duration with count() the absolute value of _Dur.count() return _Dur < duration<_Rep, _Period>::zero() ? duration<_Rep, _Period>::zero() - _Dur : _Dur; } // duration TYPES using nanoseconds = duration; using microseconds = duration; using milliseconds = duration; using seconds = duration; using minutes = duration>; using hours = duration>; // time_point ARITHMETIC template _NODISCARD constexpr time_point<_Clock, common_type_t<_Duration, duration<_Rep, _Period>>> operator+(const time_point<_Clock, _Duration>& _Left, const duration<_Rep, _Period>& _Right) noexcept( is_arithmetic_v&& is_arithmetic_v<_Rep>) /* strengthened */ { using _RT = time_point<_Clock, common_type_t<_Duration, duration<_Rep, _Period>>>; return _RT(_Left.time_since_epoch() + _Right); } template _NODISCARD constexpr time_point<_Clock, common_type_t, _Duration>> operator+(const duration<_Rep, _Period>& _Left, const time_point<_Clock, _Duration>& _Right) noexcept( is_arithmetic_v<_Rep>&& is_arithmetic_v) /* strengthened */ { return _Right + _Left; } template _NODISCARD constexpr time_point<_Clock, common_type_t<_Duration, duration<_Rep, _Period>>> operator-(const time_point<_Clock, _Duration>& _Left, const duration<_Rep, _Period>& _Right) noexcept( is_arithmetic_v&& is_arithmetic_v<_Rep>) /* strengthened */ { using _RT = time_point<_Clock, common_type_t<_Duration, duration<_Rep, _Period>>>; return _RT(_Left.time_since_epoch() - _Right); } template _NODISCARD constexpr common_type_t<_Duration1, _Duration2> operator-(const time_point<_Clock, _Duration1>& _Left, const time_point<_Clock, _Duration2>& _Right) noexcept( is_arithmetic_v&& is_arithmetic_v) /* strengthened */ { return _Left.time_since_epoch() - _Right.time_since_epoch(); } // time_point COMPARISONS template _NODISCARD constexpr bool operator==(const time_point<_Clock, _Duration1>& _Left, const time_point<_Clock, _Duration2>& _Right) noexcept( is_arithmetic_v&& is_arithmetic_v) /* strengthened */ { return _Left.time_since_epoch() == _Right.time_since_epoch(); } template _NODISCARD constexpr bool operator!=(const time_point<_Clock, _Duration1>& _Left, const time_point<_Clock, _Duration2>& _Right) noexcept( is_arithmetic_v&& is_arithmetic_v) /* strengthened */ { return !(_Left == _Right); } template _NODISCARD constexpr bool operator<(const time_point<_Clock, _Duration1>& _Left, const time_point<_Clock, _Duration2>& _Right) noexcept( is_arithmetic_v&& is_arithmetic_v) /* strengthened */ { return _Left.time_since_epoch() < _Right.time_since_epoch(); } template _NODISCARD constexpr bool operator<=(const time_point<_Clock, _Duration1>& _Left, const time_point<_Clock, _Duration2>& _Right) noexcept( is_arithmetic_v&& is_arithmetic_v) /* strengthened */ { return !(_Right < _Left); } template _NODISCARD constexpr bool operator>(const time_point<_Clock, _Duration1>& _Left, const time_point<_Clock, _Duration2>& _Right) noexcept( is_arithmetic_v&& is_arithmetic_v) /* strengthened */ { return _Right < _Left; } template _NODISCARD constexpr bool operator>=(const time_point<_Clock, _Duration1>& _Left, const time_point<_Clock, _Duration2>& _Right) noexcept( is_arithmetic_v&& is_arithmetic_v) /* strengthened */ { return !(_Left < _Right); } // FUNCTION TEMPLATE time_point_cast template , int> = 0> _NODISCARD constexpr time_point<_Clock, _To> time_point_cast(const time_point<_Clock, _Duration>& _Time) noexcept( is_arithmetic_v&& is_arithmetic_v) /* strengthened */ { // change the duration type of a time_point; truncate return time_point<_Clock, _To>(chrono::duration_cast<_To>(_Time.time_since_epoch())); } // FUNCTION TEMPLATE floor (for time_point instances) template , int> = 0> _NODISCARD constexpr time_point<_Clock, _To> floor(const time_point<_Clock, _Duration>& _Time) noexcept( is_arithmetic_v&& is_arithmetic_v) /* strengthened */ { // change the duration type of a time_point; round towards negative infinity return time_point<_Clock, _To>(chrono::floor<_To>(_Time.time_since_epoch())); } // FUNCTION TEMPLATE ceil (for time_point instances) template , int> = 0> _NODISCARD constexpr time_point<_Clock, _To> ceil(const time_point<_Clock, _Duration>& _Time) noexcept( is_arithmetic_v&& is_arithmetic_v) /* strengthened */ { // change the duration type of a time_point; round towards positive infinity return time_point<_Clock, _To>(chrono::ceil<_To>(_Time.time_since_epoch())); } // FUNCTION TEMPLATE round (for time_point instances) template && !treat_as_floating_point_v, int> = 0> _NODISCARD constexpr time_point<_Clock, _To> round(const time_point<_Clock, _Duration>& _Time) noexcept( is_arithmetic_v&& is_arithmetic_v) /* strengthened */ { // change the duration type of a time_point; round to nearest, ties to even return time_point<_Clock, _To>(chrono::round<_To>(_Time.time_since_epoch())); } // CLOCKS struct system_clock { // wraps GetSystemTimePreciseAsFileTime/GetSystemTimeAsFileTime using rep = long long; using period = ratio_multiply, nano>; using duration = chrono::duration; using time_point = chrono::time_point; static constexpr bool is_steady = false; _NODISCARD static time_point now() noexcept { // get current time return time_point(duration(_Xtime_get_ticks())); } _NODISCARD static __time64_t to_time_t(const time_point& _Time) noexcept { // convert to __time64_t return static_cast<__time64_t>(_Time.time_since_epoch().count() / _XTIME_TICKS_PER_TIME_T); } _NODISCARD static time_point from_time_t(__time64_t _Tm) noexcept { // convert from __time64_t return time_point(duration(_Tm * _XTIME_TICKS_PER_TIME_T)); } }; struct steady_clock { // wraps QueryPerformanceCounter using rep = long long; using period = nano; using duration = nanoseconds; using time_point = chrono::time_point; static constexpr bool is_steady = true; _NODISCARD static time_point now() noexcept { // get current time #if (defined(_M_IX86) || defined(_M_X64) || defined(_M_ARM) || defined(_M_ARM64)) && !defined(_M_CEE_PURE) // Implement atomics avoiding header dependency static volatile long long _Cached_freq = LLONG_MAX; static volatile long long _Cached_ctr_base = LLONG_MAX; static volatile long long _Cached_result_base = LLONG_MAX; const long long _Freq_from_cache = _Atomic_load_ll_relaxed(&_Cached_freq); const long long _Ctr_base = _Atomic_load_ll_relaxed(&_Cached_ctr_base); const long long _Result_base = _Atomic_load_ll_relaxed(&_Cached_result_base); if (_Freq_from_cache != LLONG_MAX && _Ctr_base != LLONG_MAX && _Result_base != LLONG_MAX) { // Fast path const long long _Ctr = _Query_perf_counter(); return time_point(duration(_Result_base + (_Ctr - _Ctr_base) * period::den / _Freq_from_cache)); } // Calculate with two divisions to prevent overflow const long long _Freq = _Query_perf_frequency(); const long long _Ctr = _Query_perf_counter(); const long long _Result = _Scale_large_counter(_Ctr, _Freq); if (_Atomic_compare_exchange_strong_ll_seq_cst(&_Cached_freq, _Freq, LLONG_MAX)) { // This is the first result, save current result as base for fast path _Atomic_compare_exchange_strong_ll_seq_cst(&_Cached_ctr_base, _Ctr, LLONG_MAX); _Atomic_compare_exchange_strong_ll_seq_cst(&_Cached_result_base, _Result, LLONG_MAX); } // if _Result is not saved as first, it is still compatible with fast result return time_point(duration(_Result)); #else // ^^^ known hardware && !defined(_M_CEE_PURE) / unknown hardware || defined(_M_CEE_PURE) vvv const long long _Freq = _Query_perf_frequency(); // doesn't change after system boot const long long _Ctr = _Query_perf_counter(); return time_point(duration(_Scale_large_counter(_Ctr, _Freq))); #endif // (defined(_M_IX86) || defined(_M_X64) || defined(_M_ARM) || defined(_M_ARM64)) && !defined(_M_CEE_PURE) } private: _NODISCARD static long long _Scale_large_counter(const long long _Ctr, const long long _Freq) noexcept { static_assert(period::num == 1, "This assumes period::num == 1."); // Instead of just having "(_Ctr * period::den) / _Freq", // the algorithm below prevents overflow when _Ctr is sufficiently large. // It assumes that _Freq * period::den does not overflow, which is currently true for nano period. // It is not realistic for _Ctr to accumulate to large values from zero with this assumption, // but the initial value of _Ctr could be large. const long long _Whole = (_Ctr / _Freq) * period::den; const long long _Part = (_Ctr % _Freq) * period::den / _Freq; return _Whole + _Part; } }; using high_resolution_clock = steady_clock; } // namespace chrono // HELPERS template _NODISCARD bool _To_xtime_10_day_clamped(_CSTD xtime& _Xt, const chrono::duration<_Rep, _Period>& _Rel_time) noexcept( is_arithmetic_v<_Rep>) { // Convert duration to xtime, maximum 10 days from now, returns whether clamping occurred. // If clamped, timeouts will be transformed into spurious non-timeout wakes, due to ABI restrictions where // the other side of the DLL boundary overflows int32_t milliseconds. // Every function calling this one is TRANSITION, ABI constexpr chrono::nanoseconds _Ten_days{chrono::hours{24} * 10}; constexpr chrono::duration _Ten_days_d{_Ten_days}; chrono::nanoseconds _T0 = chrono::system_clock::now().time_since_epoch(); const bool _Clamped = _Ten_days_d < _Rel_time; if (_Clamped) { _T0 += _Ten_days; } else { _T0 += chrono::duration_cast(_Rel_time); } const auto _Whole_seconds = chrono::duration_cast(_T0); _Xt.sec = _Whole_seconds.count(); _T0 -= _Whole_seconds; _Xt.nsec = static_cast(_T0.count()); return _Clamped; } // duration LITERALS inline namespace literals { inline namespace chrono_literals { _NODISCARD constexpr chrono::hours operator"" h(unsigned long long _Val) noexcept /* strengthened */ { return chrono::hours(_Val); } _NODISCARD constexpr chrono::duration> operator"" h(long double _Val) noexcept /* strengthened */ { return chrono::duration>(_Val); } _NODISCARD constexpr chrono::minutes(operator"" min)(unsigned long long _Val) noexcept /* strengthened */ { return chrono::minutes(_Val); } _NODISCARD constexpr chrono::duration>(operator"" min)(long double _Val) noexcept /* strengthened */ { return chrono::duration>(_Val); } _NODISCARD constexpr chrono::seconds operator"" s(unsigned long long _Val) noexcept /* strengthened */ { return chrono::seconds(_Val); } _NODISCARD constexpr chrono::duration operator"" s(long double _Val) noexcept /* strengthened */ { return chrono::duration(_Val); } _NODISCARD constexpr chrono::milliseconds operator"" ms(unsigned long long _Val) noexcept /* strengthened */ { return chrono::milliseconds(_Val); } _NODISCARD constexpr chrono::duration operator"" ms(long double _Val) noexcept /* strengthened */ { return chrono::duration(_Val); } _NODISCARD constexpr chrono::microseconds operator"" us(unsigned long long _Val) noexcept /* strengthened */ { return chrono::microseconds(_Val); } _NODISCARD constexpr chrono::duration operator"" us(long double _Val) noexcept /* strengthened */ { return chrono::duration(_Val); } _NODISCARD constexpr chrono::nanoseconds operator"" ns(unsigned long long _Val) noexcept /* strengthened */ { return chrono::nanoseconds(_Val); } _NODISCARD constexpr chrono::duration operator"" ns(long double _Val) noexcept /* strengthened */ { return chrono::duration(_Val); } } // namespace chrono_literals } // namespace literals namespace chrono { using namespace literals::chrono_literals; } // namespace chrono _STD_END #pragma pop_macro("new") _STL_RESTORE_CLANG_WARNINGS #pragma warning(pop) #pragma pack(pop) #endif // _STL_COMPILER_PREPROCESSOR #endif // _CHRONO_