// __msvc_chrono.hpp internal header // Copyright (c) Microsoft Corporation. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception #pragma once #ifndef __MSVC_CHRONO_HPP #define __MSVC_CHRONO_HPP #include #if _STL_COMPILER_PREPROCESSOR #include #include #include #include #include #include #if _HAS_CXX20 #include #endif #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 { 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; 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)(); } }; #if _HAS_CXX20 template inline constexpr bool _Is_clock_v = false; template inline constexpr bool _Is_clock_v<_Clock, void_t> = true; // TRANSITION, GH-602 template struct is_clock : bool_constant<_Is_clock_v<_Clock>> {}; template inline constexpr bool is_clock_v = _Is_clock_v<_Clock>; #endif // _HAS_CXX20 template > class duration; 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>, "N4885 [time.point.general]/1 mandates Duration to be a specialization of chrono::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; } #if _HAS_CXX20 constexpr time_point& operator++() noexcept(is_arithmetic_v) /* strengthened */ { ++_MyDur; return *this; } constexpr time_point operator++(int) noexcept(is_arithmetic_v) /* strengthened */ { return time_point{_MyDur++}; } constexpr time_point& operator--() noexcept(is_arithmetic_v) /* strengthened */ { --_MyDur; return *this; } constexpr time_point operator--(int) noexcept(is_arithmetic_v) /* strengthened */ { return time_point{_MyDur--}; } #endif // _HAS_CXX20 _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 template _INLINE_VAR constexpr bool _Is_trivially_swappable_v> = _Is_trivially_swappable_v<_Rep>; template _INLINE_VAR constexpr bool _Is_trivially_swappable_v> = _Is_trivially_swappable_v<_Duration>; template ::value) <= INTMAX_MAX / _Bx)> struct _Lcm : integral_constant::value) * _Bx> {}; template struct _Lcm<_Ax, _Bx, false> {}; template struct common_type<_CHRONO duration<_Rep1, _Period1>, _CHRONO duration<_Rep2, _Period2>> { 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, _Duration1>, _CHRONO time_point<_Clock, _Duration2>> { // common type of two time points using type = _CHRONO time_point<_Clock, common_type_t<_Duration1, _Duration2>>; }; namespace chrono { 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()); } 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(); } #if !_HAS_CXX20 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); } #endif // !_HAS_CXX20 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); } #ifdef __cpp_lib_concepts // clang-format off template requires three_way_comparable, duration<_Rep2, _Period2>>::rep> _NODISCARD constexpr auto operator<=>(const duration<_Rep1, _Period1>& _Left, const duration<_Rep2, _Period2>& _Right) noexcept( is_arithmetic_v<_Rep1>&& is_arithmetic_v<_Rep2>) /* strengthened */ { // clang-format on using _CT = common_type_t, duration<_Rep2, _Period2>>; return _CT(_Left).count() <=> _CT(_Right).count(); } #endif // defined(__cpp_lib_concepts) 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))); } } } 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; } 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; } 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; } 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; } using nanoseconds = duration; using microseconds = duration; using milliseconds = duration; using seconds = duration; using minutes = duration>; using hours = duration>; #if _HAS_CXX20 using days = duration, hours::period>>; using weeks = duration, days::period>>; using years = duration, days::period>>; using months = duration>>; #endif // _HAS_CXX20 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(); } 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(); } #if !_HAS_CXX20 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); } #endif // !_HAS_CXX20 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); } #ifdef __cpp_lib_concepts template _Duration2> _NODISCARD constexpr auto 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(); } #endif // defined(__cpp_lib_concepts) 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())); } 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())); } 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())); } 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())); } struct system_clock { // wraps GetSystemTimePreciseAsFileTime/GetSystemTimeAsFileTime using rep = long long; using period = ratio<1, 10'000'000>; // 100 nanoseconds 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 duration_cast(_Time.time_since_epoch()).count(); } _NODISCARD static time_point from_time_t(__time64_t _Tm) noexcept { // convert from __time64_t return time_point{seconds{_Tm}}; } }; #if _HAS_CXX20 template using sys_time = time_point; using sys_seconds = sys_time; using sys_days = sys_time; #endif // _HAS_CXX20 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 const long long _Freq = _Query_perf_frequency(); // doesn't change after system boot const long long _Ctr = _Query_perf_counter(); static_assert(period::num == 1, "This assumes period::num == 1."); // 10 MHz is a very common QPC frequency on modern PCs. Optimizing for // this specific frequency can double the performance of this function by // avoiding the expensive frequency conversion path. constexpr long long _TenMHz = 10'000'000; if (_Freq == _TenMHz) { static_assert(period::den % _TenMHz == 0, "It should never fail."); constexpr long long _Multiplier = period::den / _TenMHz; return time_point(duration(_Ctr * _Multiplier)); } else { // 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 time_point(duration(_Whole + _Part)); } } }; using high_resolution_clock = steady_clock; } // namespace chrono 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 _Tx0 = _CHRONO system_clock::now().time_since_epoch(); const bool _Clamped = _Ten_days_d < _Rel_time; if (_Clamped) { _Tx0 += _Ten_days; } else { _Tx0 += _CHRONO duration_cast<_CHRONO nanoseconds>(_Rel_time); } const auto _Whole_seconds = _CHRONO duration_cast<_CHRONO seconds>(_Tx0); _Xt.sec = _Whole_seconds.count(); _Tx0 -= _Whole_seconds; _Xt.nsec = static_cast(_Tx0.count()); return _Clamped; } 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 // __MSVC_CHRONO_HPP