Skip to content

Commit

Permalink
Eliminate xtime and its member sec, nsec (#3594)
Browse files Browse the repository at this point in the history
  • Loading branch information
frederick-vs-ja authored Mar 28, 2023
1 parent 542c46a commit c2527c4
Show file tree
Hide file tree
Showing 15 changed files with 118 additions and 201 deletions.
12 changes: 6 additions & 6 deletions stl/inc/__msvc_chrono.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -695,10 +695,10 @@ 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>) {
// 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
_NODISCARD bool _To_timespec64_sys_10_day_clamped(
_timespec64& _Ts64, const _CHRONO duration<_Rep, _Period>& _Rel_time) noexcept(is_arithmetic_v<_Rep>) {
// Convert duration to _timespec64 representing system time, 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};
Expand All @@ -712,9 +712,9 @@ _NODISCARD bool _To_xtime_10_day_clamped(_CSTD xtime& _Xt, const _CHRONO duratio
}

const auto _Whole_seconds = _CHRONO duration_cast<_CHRONO seconds>(_Tx0);
_Xt.sec = _Whole_seconds.count();
_Ts64.tv_sec = _Whole_seconds.count();
_Tx0 -= _Whole_seconds;
_Xt.nsec = static_cast<long>(_Tx0.count());
_Ts64.tv_nsec = static_cast<long>(_Tx0.count());
return _Clamped;
}

Expand Down
33 changes: 9 additions & 24 deletions stl/inc/condition_variable
Original file line number Diff line number Diff line change
Expand Up @@ -122,10 +122,10 @@ public:
}

// TRANSITION, ABI: The standard says that we should use a steady clock,
// but unfortunately our ABI speaks struct xtime, which is relative to the system clock.
_CSTD xtime _Tgt;
const bool _Clamped = _To_xtime_10_day_clamped(_Tgt, _Rel_time);
const cv_status _Result = _Wait_until(_Lck, &_Tgt);
// but unfortunately our ABI relies on the system clock.
_timespec64 _Tgt;
const bool _Clamped = _To_timespec64_sys_10_day_clamped(_Tgt, _Rel_time);
const cv_status _Result = _Wait_until_sys_time(_Lck, &_Tgt);
if (_Clamped) {
return cv_status::no_timeout;
}
Expand All @@ -139,22 +139,6 @@ public:
return wait_until(_Lck, _To_absolute_time(_Rel_time), _STD move(_Pred));
}

template <class _Lock>
cv_status wait_until(_Lock& _Lck, const xtime* const _Abs_time) { // wait for signal with timeout
return _Wait_until(_Lck, _Abs_time);
}

template <class _Lock, class _Predicate>
bool wait_until(_Lock& _Lck, const xtime* const _Abs_time, _Predicate _Pred) {
// wait for signal with timeout and check predicate
while (!_Pred()) {
if (_Wait_until(_Lck, _Abs_time) == cv_status::timeout) {
return _Pred();
}
}
return true;
}

#if _HAS_CXX20
private:
struct _Cv_any_notify_all {
Expand Down Expand Up @@ -221,9 +205,9 @@ public:

const auto _Rel_time = _Abs_time - _Now;
// TRANSITION, ABI: The standard says that we should use a steady clock,
// but unfortunately our ABI speaks struct xtime, which is relative to the system clock.
_CSTD xtime _Tgt;
(void) _To_xtime_10_day_clamped(_Tgt, _Rel_time);
// but unfortunately our ABI relies on the system clock.
_timespec64 _Tgt;
(void) _To_timespec64_sys_10_day_clamped(_Tgt, _Rel_time);
(void) _Cnd_timedwait(_Mycnd(), _Myptr->_Mymtx(), &_Tgt);
_Guard_unlocks_before_locking_outer.unlock();
} // relock
Expand All @@ -247,7 +231,8 @@ private:
}

template <class _Lock>
cv_status _Wait_until(_Lock& _Lck, const xtime* const _Abs_time) { // wait for signal with timeout
cv_status _Wait_until_sys_time(_Lock& _Lck, const _timespec64* const _Abs_time) {
// wait for signal with timeout
const shared_ptr<mutex> _Ptr = _Myptr; // for immunity to *this destruction
unique_lock<mutex> _Guard{*_Ptr};
_Unlock_guard<_Lock> _Unlock_outer{_Lck};
Expand Down
81 changes: 28 additions & 53 deletions stl/inc/mutex
Original file line number Diff line number Diff line change
Expand Up @@ -202,11 +202,6 @@ public:
#endif // _HAS_CXX20
}

_NODISCARD_CTOR_LOCK unique_lock(_Mutex& _Mtx, const xtime* _Abs_time)
: _Pmtx(_STD addressof(_Mtx)), _Owns(false) { // try to lock until _Abs_time
_Owns = _Pmtx->try_lock_until(_Abs_time);
}

_NODISCARD_CTOR_LOCK unique_lock(unique_lock&& _Other) noexcept : _Pmtx(_Other._Pmtx), _Owns(_Other._Owns) {
_Other._Pmtx = nullptr;
_Other._Owns = false;
Expand Down Expand Up @@ -264,12 +259,6 @@ public:
return _Owns;
}

_NODISCARD_TRY_CHANGE_STATE bool try_lock_until(const xtime* _Abs_time) {
_Validate();
_Owns = _Pmtx->try_lock_until(_Abs_time);
return _Owns;
}

void unlock() {
if (!_Pmtx || !_Owns) {
_Throw_system_error(errc::operation_not_permitted);
Expand Down Expand Up @@ -690,10 +679,10 @@ public:
}

// TRANSITION, ABI: The standard says that we should use a steady clock,
// but unfortunately our ABI speaks struct xtime, which is relative to the system clock.
_CSTD xtime _Tgt;
const bool _Clamped = _To_xtime_10_day_clamped(_Tgt, _Rel_time);
const cv_status _Result = wait_until(_Lck, &_Tgt);
// but unfortunately our ABI relies on the system clock.
_timespec64 _Tgt;
const bool _Clamped = _To_timespec64_sys_10_day_clamped(_Tgt, _Rel_time);
const cv_status _Result = _Wait_until_sys_time(_Lck, &_Tgt);
if (_Clamped) {
return cv_status::no_timeout;
}
Expand All @@ -719,9 +708,9 @@ public:
return cv_status::timeout;
}

_CSTD xtime _Tgt;
(void) _To_xtime_10_day_clamped(_Tgt, _Abs_time - _Now);
const cv_status _Result = wait_until(_Lck, &_Tgt);
_timespec64 _Tgt;
(void) _To_timespec64_sys_10_day_clamped(_Tgt, _Abs_time - _Now);
const cv_status _Result = _Wait_until_sys_time(_Lck, &_Tgt);
if (_Result == cv_status::no_timeout) {
return cv_status::no_timeout;
}
Expand All @@ -738,28 +727,6 @@ public:
return _Wait_until1(_Lck, _Abs_time, _Pred);
}

cv_status wait_until(unique_lock<mutex>& _Lck, const xtime* _Abs_time) {
// wait for signal with timeout
if (!_Mtx_current_owns(_Lck.mutex()->_Mymtx())) {
_Throw_Cpp_error(_OPERATION_NOT_PERMITTED);
}

// Nothing to do to comply with LWG-2135 because std::mutex lock/unlock are nothrow
const int _Res = _Cnd_timedwait(_Mycnd(), _Lck.mutex()->_Mymtx(), _Abs_time);

if (_Res == _Thrd_success) {
return cv_status::no_timeout;
} else {
return cv_status::timeout;
}
}

template <class _Predicate>
bool wait_until(unique_lock<mutex>& _Lck, const xtime* _Abs_time, _Predicate _Pred) {
// wait for signal with timeout and check predicate
return _Wait_until1(_Lck, _Abs_time, _Pred);
}

_NODISCARD native_handle_type native_handle() noexcept /* strengthened */ {
return _Mycnd();
}
Expand All @@ -779,11 +746,27 @@ private:
return reinterpret_cast<_Cnd_t>(&_Cnd_storage);
}

cv_status _Wait_until_sys_time(unique_lock<mutex>& _Lck, const _timespec64* _Abs_time) {
// wait for signal with timeout
if (!_Mtx_current_owns(_Lck.mutex()->_Mymtx())) {
_Throw_Cpp_error(_OPERATION_NOT_PERMITTED);
}

// Nothing to do to comply with LWG-2135 because std::mutex lock/unlock are nothrow
const int _Res = _Cnd_timedwait(_Mycnd(), _Lck.mutex()->_Mymtx(), _Abs_time);

if (_Res == _Thrd_success) {
return cv_status::no_timeout;
} else {
return cv_status::timeout;
}
}

template <class _Predicate>
bool _Wait_until1(unique_lock<mutex>& _Lck, const xtime* _Abs_time, _Predicate& _Pred) {
bool _Wait_until1(unique_lock<mutex>& _Lck, const _timespec64* _Abs_time, _Predicate& _Pred) {
// wait for signal with timeout and check predicate
while (!_Pred()) {
if (wait_until(_Lck, _Abs_time) == cv_status::timeout) {
if (_Wait_until_sys_time(_Lck, _Abs_time) == cv_status::timeout) {
return _Pred();
}
}
Expand All @@ -800,9 +783,9 @@ private:
return false;
}

_CSTD xtime _Tgt;
const bool _Clamped = _To_xtime_10_day_clamped(_Tgt, _Abs_time - _Now);
if (wait_until(_Lck, &_Tgt) == cv_status::timeout && !_Clamped) {
_timespec64 _Tgt;
const bool _Clamped = _To_timespec64_sys_10_day_clamped(_Tgt, _Abs_time - _Now);
if (_Wait_until_sys_time(_Lck, &_Tgt) == cv_status::timeout && !_Clamped) {
return _Pred();
}
}
Expand Down Expand Up @@ -880,10 +863,6 @@ public:
return _Try_lock_until(_Abs_time);
}

_NODISCARD_TRY_CHANGE_STATE bool try_lock_until(const xtime* _Abs_time) { // try to lock the mutex with timeout
return _Try_lock_until(_Abs_time);
}

private:
mutex _My_mutex;
condition_variable _My_cond;
Expand Down Expand Up @@ -997,10 +976,6 @@ public:
return _Try_lock_until(_Abs_time);
}

_NODISCARD_TRY_CHANGE_STATE bool try_lock_until(const xtime* _Abs_time) { // try to lock the mutex with timeout
return _Try_lock_until(_Abs_time);
}

private:
mutex _My_mutex;
condition_variable _My_cond;
Expand Down
5 changes: 0 additions & 5 deletions stl/inc/shared_mutex
Original file line number Diff line number Diff line change
Expand Up @@ -189,11 +189,6 @@ public:
return _Try_lock_shared_until(_Abs_time);
}

_NODISCARD_TRY_CHANGE_STATE bool try_lock_shared_until(
const xtime* _Abs_time) { // try to lock non-exclusive until absolute time
return _Try_lock_shared_until(_Abs_time);
}

void unlock_shared() { // unlock non-exclusive
_Read_cnt_t _Local_readers;
bool _Local_writing;
Expand Down
8 changes: 2 additions & 6 deletions stl/inc/thread
Original file line number Diff line number Diff line change
Expand Up @@ -181,10 +181,6 @@ namespace this_thread {
_Thrd_yield();
}

inline void sleep_until(const xtime* _Abs_time) {
_Thrd_sleep(_Abs_time);
}

_EXPORT_STD template <class _Clock, class _Duration>
void sleep_until(const chrono::time_point<_Clock, _Duration>& _Abs_time) {
#if _HAS_CXX20
Expand All @@ -196,8 +192,8 @@ namespace this_thread {
return;
}

_CSTD xtime _Tgt;
(void) _To_xtime_10_day_clamped(_Tgt, _Abs_time - _Now);
_timespec64 _Tgt;
(void) _To_timespec64_sys_10_day_clamped(_Tgt, _Abs_time - _Now);
_Thrd_sleep(&_Tgt);
}
}
Expand Down
6 changes: 3 additions & 3 deletions stl/inc/xthreads.h
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ enum { _Thrd_success, _Thrd_nomem, _Thrd_timedout, _Thrd_busy, _Thrd_error };
// threads
_CRTIMP2_PURE int __cdecl _Thrd_detach(_Thrd_t);
_CRTIMP2_PURE int __cdecl _Thrd_join(_Thrd_t, int*);
_CRTIMP2_PURE void __cdecl _Thrd_sleep(const xtime*);
_CRTIMP2_PURE void __cdecl _Thrd_sleep(const _timespec64*);
_CRTIMP2_PURE void __cdecl _Thrd_yield();
_CRTIMP2_PURE unsigned int __cdecl _Thrd_hardware_concurrency();
_CRTIMP2_PURE _Thrd_id_t __cdecl _Thrd_id();
Expand All @@ -87,7 +87,7 @@ _CRTIMP2_PURE void __cdecl _Mtx_destroy_in_situ(_Mtx_t);
_CRTIMP2_PURE int __cdecl _Mtx_current_owns(_Mtx_t);
_CRTIMP2_PURE int __cdecl _Mtx_lock(_Mtx_t);
_CRTIMP2_PURE int __cdecl _Mtx_trylock(_Mtx_t);
_CRTIMP2_PURE int __cdecl _Mtx_timedlock(_Mtx_t, const xtime*);
_CRTIMP2_PURE int __cdecl _Mtx_timedlock(_Mtx_t, const _timespec64*);
_CRTIMP2_PURE int __cdecl _Mtx_unlock(_Mtx_t); // TRANSITION, ABI: always returns _Thrd_success

_CRTIMP2_PURE void* __cdecl _Mtx_getconcrtcs(_Mtx_t);
Expand All @@ -110,7 +110,7 @@ _CRTIMP2_PURE void __cdecl _Cnd_destroy(_Cnd_t);
_CRTIMP2_PURE void __cdecl _Cnd_init_in_situ(_Cnd_t);
_CRTIMP2_PURE void __cdecl _Cnd_destroy_in_situ(_Cnd_t);
_CRTIMP2_PURE int __cdecl _Cnd_wait(_Cnd_t, _Mtx_t); // TRANSITION, ABI: Always returns _Thrd_success
_CRTIMP2_PURE int __cdecl _Cnd_timedwait(_Cnd_t, _Mtx_t, const xtime*);
_CRTIMP2_PURE int __cdecl _Cnd_timedwait(_Cnd_t, _Mtx_t, const _timespec64*);
_CRTIMP2_PURE int __cdecl _Cnd_broadcast(_Cnd_t); // TRANSITION, ABI: Always returns _Thrd_success
_CRTIMP2_PURE int __cdecl _Cnd_signal(_Cnd_t); // TRANSITION, ABI: Always returns _Thrd_success
_CRTIMP2_PURE void __cdecl _Cnd_register_at_thread_exit(_Cnd_t, _Mtx_t, int*);
Expand Down
9 changes: 2 additions & 7 deletions stl/inc/xtimec.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,17 +20,12 @@ _STL_DISABLE_CLANG_WARNINGS

_EXTERN_C

struct xtime { // store time with nanosecond resolution
__time64_t sec;
long nsec;
};

_CRTIMP2_PURE long __cdecl _Xtime_diff_to_millis2(const xtime*, const xtime*);
_CRTIMP2_PURE long __cdecl _Xtime_diff_to_millis2(const _timespec64*, const _timespec64*);
_CRTIMP2_PURE long long __cdecl _Xtime_get_ticks();

#ifdef _CRTBLD
// Used by several src files, but not dllexported.
void _Xtime_get2(xtime*);
void _Timespec64_get_sys(_timespec64*);
#endif // _CRTBLD

_CRTIMP2_PURE long long __cdecl _Query_perf_counter();
Expand Down
9 changes: 5 additions & 4 deletions stl/src/cond.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,19 +60,20 @@ int _Cnd_wait(const _Cnd_t cond, const _Mtx_t mtx) { // wait until signaled
return _Thrd_success; // TRANSITION, ABI: Always returns _Thrd_success
}

int _Cnd_timedwait(const _Cnd_t cond, const _Mtx_t mtx, const xtime* const target) { // wait until signaled or timeout
// wait until signaled or timeout
int _Cnd_timedwait(const _Cnd_t cond, const _Mtx_t mtx, const _timespec64* const target) {
int res = _Thrd_success;
const auto cs = static_cast<Concurrency::details::stl_critical_section_interface*>(_Mtx_getconcrtcs(mtx));
if (target == nullptr) { // no target time specified, wait on mutex
_Mtx_clear_owner(mtx);
cond->_get_cv()->wait(cs);
_Mtx_reset_owner(mtx);
} else { // target time specified, wait for it
xtime now;
_Xtime_get2(&now);
_timespec64 now;
_Timespec64_get_sys(&now);
_Mtx_clear_owner(mtx);
if (!cond->_get_cv()->wait_for(cs, _Xtime_diff_to_millis2(target, &now))) { // report timeout
_Xtime_get2(&now);
_Timespec64_get_sys(&now);
if (_Xtime_diff_to_millis2(target, &now) == 0) {
res = _Thrd_timedout;
}
Expand Down
10 changes: 5 additions & 5 deletions stl/src/cthread.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -72,13 +72,13 @@ int _Thrd_detach(_Thrd_t thr) { // tell OS to release thread's resources when it
return CloseHandle(thr._Hnd) ? _Thrd_success : _Thrd_error;
}

void _Thrd_sleep(const xtime* xt) { // suspend thread until time xt
xtime now;
_Xtime_get2(&now);
void _Thrd_sleep(const _timespec64* xt) { // suspend thread until time xt
_timespec64 now;
_Timespec64_get_sys(&now);
do { // sleep and check time
Sleep(_Xtime_diff_to_millis2(xt, &now));
_Xtime_get2(&now);
} while (now.sec < xt->sec || now.sec == xt->sec && now.nsec < xt->nsec);
_Timespec64_get_sys(&now);
} while (now.tv_sec < xt->tv_sec || now.tv_sec == xt->tv_sec && now.tv_nsec < xt->tv_nsec);
}

void _Thrd_yield() { // surrender remainder of timeslice
Expand Down
Loading

0 comments on commit c2527c4

Please sign in to comment.