Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
b925e16
Implement `file_time` ↔ UTC conversion with leap second handling
statementreply May 1, 2021
375fe5a
Code cleanup
statementreply May 4, 2021
319e518
Move _Days_from_civil out for use in C++14 mode
statementreply May 4, 2021
22ccb75
Implement `system_clock::now`
statementreply May 4, 2021
2a9b591
Update `_To_xtime_10_day_clamped` to call `_Xtime_get_ticks` directly
statementreply May 4, 2021
1fa5f71
Add tests for `Clock::now`
statementreply May 4, 2021
5c6f625
_Uglify import lib code
statementreply May 4, 2021
c3038de
Shorten link to fit in 120 columns
statementreply May 4, 2021
7f2a5bd
Move bit operator overloads out of `extern C`
statementreply May 4, 2021
4f3d01c
Merge branch 'main' into windows-leap-second
statementreply Jul 26, 2021
a698c6d
Implement `file_time` ↔ `sys_time` conversion
statementreply Jul 26, 2021
49bce5a
Code review comments
statementreply Jul 26, 2021
7373b98
`nextafter` requires `#include <cmath>`
statementreply Jul 26, 2021
44d4bbb
Merge branch 'main' into windows-leap-second
statementreply Aug 21, 2021
1a22caf
Remove `#include <chrono>` from import library source
statementreply Aug 21, 2021
e4e88ec
Centralize FILETIME offset value
statementreply Aug 21, 2021
4296d97
Explain the magic tolerance
statementreply Aug 21, 2021
1336e1f
Merge branch 'main' into windows-leap-second
statementreply Aug 28, 2021
c5ee629
Implement `file_time` ↔ `utc_time` conversion
statementreply Sep 4, 2021
96d8501
Fix tests
statementreply Sep 4, 2021
0c3c998
Fix tests
statementreply Sep 5, 2021
cb7a139
Merge remote-tracking branch 'upstream/main' into windows-leap-second
statementreply Oct 2, 2021
5683bc0
Implement `file_time` formatting
statementreply Oct 2, 2021
4767cfe
Merge remote-tracking branch 'upstream/main' into windows-leap-second
statementreply Oct 22, 2021
d573b1e
Merge remote-tracking branch 'upstream/main' into windows-leap-second
statementreply Nov 21, 2021
29f5789
Merge remote-tracking branch 'upstream/main' into windows-leap-second
statementreply Jan 26, 2022
5b33476
Merge remote-tracking branch 'upstream/main' into windows-leap-second
statementreply May 4, 2022
e609aaa
Merge remote-tracking branch 'upstream/main' into windows-leap-second
statementreply Jun 25, 2022
fd4ce85
usual_winsdk_matrix.lst no longer exists
statementreply Jun 25, 2022
bdae556
Merge remote-tracking branch 'upstream/main' into windows-leap-second
statementreply Jul 31, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions stl/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,7 @@ set(HEADERS
${CMAKE_CURRENT_LIST_DIR}/inc/xstddef
${CMAKE_CURRENT_LIST_DIR}/inc/xstring
${CMAKE_CURRENT_LIST_DIR}/inc/xthreads.h
${CMAKE_CURRENT_LIST_DIR}/inc/xtime0.h
${CMAKE_CURRENT_LIST_DIR}/inc/xtimec.h
${CMAKE_CURRENT_LIST_DIR}/inc/xtr1common
${CMAKE_CURRENT_LIST_DIR}/inc/xtree
Expand Down Expand Up @@ -277,6 +278,7 @@ set(IMPLIB_SOURCES
${CMAKE_CURRENT_LIST_DIR}/src/xcharconv_tables_double.cpp
${CMAKE_CURRENT_LIST_DIR}/src/xcharconv_tables_float.cpp
${CMAKE_CURRENT_LIST_DIR}/src/xonce2.cpp
${CMAKE_CURRENT_LIST_DIR}/src/xtime0.cpp
)

# The following files are linked in msvcp140[d][_clr].dll.
Expand Down
103 changes: 99 additions & 4 deletions stl/inc/__msvc_chrono.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,13 @@
#define __MSVC_CHRONO_HPP
#include <yvals.h>
#if _STL_COMPILER_PREPROCESSOR
#include <cmath>
#include <ctime>
#include <limits>
#include <ratio>
#include <type_traits>
#include <utility>
#include <xtime0.h>
#include <xtimec.h>

#if _HAS_CXX20
Expand Down Expand Up @@ -631,15 +633,108 @@ namespace chrono {
return time_point<_Clock, _To>(_CHRONO round<_To>(_Time.time_since_epoch()));
}

// _Civil_from_days and _Days_from_civil perform conversions between the dates in the (proleptic) Gregorian
// calendar and the continuous count of days since 1970-01-01.

// See comments above year_month_day::_Civil_from_days in <chrono> for an explanation of the algorithm.

// courtesy of Howard Hinnant
// https://howardhinnant.github.io/date_algorithms.html#days_from_civil
_NODISCARD constexpr int _Days_from_civil(
const int _Year, const unsigned int _Month, const unsigned int _Day) noexcept {
static_assert(numeric_limits<unsigned int>::digits >= 18,
"This algorithm has not been ported to a 16 bit unsigned integer");
static_assert(
numeric_limits<int>::digits >= 26, "This algorithm has not been ported to a 16 bit signed integer");
const int _Yp = _Year - (_Month <= 2);
const int _Century = (_Yp >= 0 ? _Yp : _Yp - 99) / 100;
const unsigned int _Mp = _Month + (_Month > 2 ? static_cast<unsigned int>(-3) : 9); // [0, 11]
// Formula 1
const int _Day_of_year = static_cast<int>(((979 * _Mp + 19) >> 5) + _Day) - 1;
// Formula 2
return ((1461 * _Yp) >> 2) - _Century + (_Century >> 2) + _Day_of_year - 719468;
}

struct system_clock;

// convert from date time breakdown (whole seconds) into sys_time
template <class _Duration = seconds>
constexpr time_point<system_clock, common_type_t<_Duration, seconds>> _Sys_seconds_from_civil(
const __std_utc_components_1s& _Utc) noexcept {
using _Common = common_type_t<_Duration, seconds>;
using _Days = _CHRONO duration<int, ratio<86'400>>;
using _Int_seconds = _CHRONO duration<int>;
const _Common _Ymd = _Days{_Days_from_civil(_Utc._Year, _Utc._Month, _Utc._Day)};
const _Common _Hms = hours{_Utc._Hour} + minutes{_Utc._Minute} + _Int_seconds{_Utc._Second};
return time_point<system_clock, _Common>{_Ymd + _Hms};
}

template <class _Duration>
struct _Utc_components {
static_assert(_Is_duration_v<_Duration>, "_Duration should be a specialization of std::chrono::duration");

__std_utc_components_1s _Whole_sec;
_Duration _Sub_sec;
};

// get the last representable value before the time point
template <class _Duration, class _Clock>
_NODISCARD static constexpr time_point<_Clock, _Duration> _Prev_time_point(
const time_point<_Clock, _Duration>& _Time) noexcept(is_arithmetic_v<typename _Duration::rep>) {
using _Rep = typename _Duration::rep;
if constexpr (treat_as_floating_point_v<_Rep>) {
// TRANSITION, GH-1909
const _Rep _Val = _Time.time_since_epoch().count();
const _Rep _Prev_val = _STD nextafter(_Val, numeric_limits<_Rep>::lowest());
return time_point<_Clock, _Duration>{_Duration{_Prev_val}};
} else {
return _Time - _Duration{1};
}
}

struct system_clock { // wraps GetSystemTimePreciseAsFileTime/GetSystemTimeAsFileTime
using rep = long long;
using period = ratio<1, 10'000'000>; // 100 nanoseconds
using duration = _CHRONO duration<rep, period>;
using time_point = _CHRONO time_point<system_clock>;
static constexpr bool is_steady = false;

#if _HAS_CXX20
template <class _Duration>
_NODISCARD static constexpr _Utc_components<common_type_t<_Duration, seconds>> _To_utc_components(
const _CHRONO time_point<system_clock, _Duration>& _Sys_time) noexcept;
#endif // _HAS_CXX20

template <class _Duration>
_NODISCARD static constexpr _CHRONO time_point<system_clock, common_type_t<_Duration, seconds>>
_From_utc_components(const _Utc_components<_Duration>& _Utc) noexcept {
using _Common = common_type_t<_Duration, seconds>;
using _Sys_time = _CHRONO time_point<system_clock, _Common>;
const _Sys_time _Sys_secs = _Sys_seconds_from_civil<_Duration>(_Utc._Whole_sec);

if (_Utc._Whole_sec._Second < 60) {
return _Sys_secs + _Utc._Sub_sec;
} else {
_STL_INTERNAL_CHECK(_Utc._Whole_sec._Second == 60);
return _CHRONO _Prev_time_point<_Common>(_Sys_secs);
}
}

_NODISCARD static time_point now() noexcept { // get current time
return time_point(duration(_Xtime_get_ticks()));
const duration _File_time{_Xtime_get_ticks() + __std_fs_file_time_epoch_adjustment}; // TRANSITION, ABI
const auto _File_seconds = _CHRONO duration_cast<seconds>(_File_time);

_Utc_components<duration> _Utc;
const __std_file_time_to_utc_errc _Ec =
__std_file_seconds_to_utc_components(_File_seconds.count(), &_Utc._Whole_sec);
_STL_INTERNAL_CHECK(_Ec == __std_file_time_to_utc_errc::_Success);
_Utc._Sub_sec = _File_time - _File_seconds;

if (_Ec != __std_file_time_to_utc_errc::_Invalid_parameter) {
return _From_utc_components(_Utc);
}

return time_point{_File_time - duration{__std_fs_file_time_epoch_adjustment}};
}

_NODISCARD static __time64_t to_time_t(const time_point& _Time) noexcept { // convert to __time64_t
Expand Down Expand Up @@ -694,15 +789,15 @@ namespace chrono {
} // namespace chrono

template <class _Rep, class _Period>
_NODISCARD bool _To_xtime_10_day_clamped(_CSTD xtime& _Xt, const _CHRONO duration<_Rep, _Period>& _Rel_time) noexcept(
is_arithmetic_v<_Rep>) {
_NODISCARD bool _To_xtime_10_day_clamped_v2(
_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<double> _Ten_days_d{_Ten_days};
_CHRONO nanoseconds _Tx0 = _CHRONO system_clock::now().time_since_epoch();
_CHRONO nanoseconds _Tx0 = _CHRONO system_clock::duration{_Xtime_get_ticks()};
const bool _Clamped = _Ten_days_d < _Rel_time;
if (_Clamped) {
_Tx0 += _Ten_days;
Expand Down
Loading