Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cleanups for condition_variable's waiting functions #3974

Merged
2 changes: 1 addition & 1 deletion stl/inc/latch
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ _STD_BEGIN
_EXPORT_STD class latch {
public:
_NODISCARD static constexpr ptrdiff_t(max)() noexcept {
return (1ULL << (sizeof(ptrdiff_t) * CHAR_BIT - 1)) - 1;
return PTRDIFF_MAX;
}

constexpr explicit latch(const ptrdiff_t _Expected) noexcept /* strengthened */ : _Counter{_Expected} {
Expand Down
71 changes: 21 additions & 50 deletions stl/inc/mutex
Original file line number Diff line number Diff line change
Expand Up @@ -574,25 +574,16 @@ public:
cv_status wait_for(unique_lock<mutex>& _Lck, const chrono::duration<_Rep, _Period>& _Rel_time) {
// wait for duration
if (_Rel_time <= chrono::duration<_Rep, _Period>::zero()) {
// we don't lock-and-relock _Lck for this case because it's not observable
CaseyCarter marked this conversation as resolved.
Show resolved Hide resolved
return cv_status::timeout;
}

// TRANSITION, ABI: The standard says that we should use a steady clock,
// 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;
}

return _Result;
return wait_until(_Lck, _To_absolute_time(_Rel_time));
}
achabense marked this conversation as resolved.
Show resolved Hide resolved

template <class _Rep, class _Period, class _Predicate>
bool wait_for(unique_lock<mutex>& _Lck, const chrono::duration<_Rep, _Period>& _Rel_time, _Predicate _Pred) {
// wait for signal with timeout and check predicate
return _Wait_until1(_Lck, _To_absolute_time(_Rel_time), _Pred);
return wait_until(_Lck, _To_absolute_time(_Rel_time), _Pass_fn(_Pred));
CaseyCarter marked this conversation as resolved.
Show resolved Hide resolved
}

template <class _Clock, class _Duration>
Expand All @@ -601,16 +592,25 @@ public:
#if _HAS_CXX20
static_assert(chrono::is_clock_v<_Clock>, "Clock type required");
#endif // _HAS_CXX20
#if _CONTAINER_DEBUG_LEVEL > 0
_STL_VERIFY(
_Lck.owns_lock(), "wait_until's caller must own the lock argument (N4958 [thread.condition.condvar]/17)");
_STL_VERIFY(_Mtx_current_owns(_Lck.mutex()->_Mymtx()),
"wait_until's calling thread must hold the lock argument's mutex (N4958 [thread.condition.condvar]/17)");
#endif // _CONTAINER_DEBUG_LEVEL > 0
for (;;) {
const auto _Now = _Clock::now();
if (_Abs_time <= _Now) {
// we don't lock-and-relock _Lck for this case because it's not observable
CaseyCarter marked this conversation as resolved.
Show resolved Hide resolved
return cv_status::timeout;
CaseyCarter marked this conversation as resolved.
Show resolved Hide resolved
}

// TRANSITION, ABI: should use a steady clock
_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) {
// Nothing to do to comply with LWG-2135 because std::mutex lock/unlock are nothrow
const _Thrd_result _Res = _Cnd_timedwait(_Mycnd(), _Lck.mutex()->_Mymtx(), &_Tgt);
if (_Res == _Thrd_result::_Success) {
CaseyCarter marked this conversation as resolved.
Show resolved Hide resolved
return cv_status::no_timeout;
}
}
Expand All @@ -623,7 +623,13 @@ public:
#if _HAS_CXX20
static_assert(chrono::is_clock_v<_Clock>, "Clock type required");
#endif // _HAS_CXX20
return _Wait_until1(_Lck, _Abs_time, _Pred);
while (!_Pred()) {
if (wait_until(_Lck, _Abs_time) == cv_status::timeout) {
return _Pred();
}
}

return true;
}

// native_handle_type and native_handle() have intentionally been removed. See GH-3820.
Expand All @@ -642,41 +648,6 @@ private:
_Cnd_t _Mycnd() noexcept { // get pointer to _Cnd_internal_imp_t inside _Cnd_storage
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 _Thrd_result _Res = _Cnd_timedwait(_Mycnd(), _Lck.mutex()->_Mymtx(), _Abs_time);

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

template <class _Clock, class _Duration, class _Predicate>
bool _Wait_until1(
unique_lock<mutex>& _Lck, const chrono::time_point<_Clock, _Duration>& _Abs_time, _Predicate& _Pred) {
while (!_Pred()) {
const auto _Now = _Clock::now();
if (_Abs_time <= _Now) {
return false;
}

_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();
}
}

return true;
}
};

struct _UInt_is_zero {
Expand Down
2 changes: 1 addition & 1 deletion stl/inc/semaphore
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ _NODISCARD unsigned long _Semaphore_remaining_timeout(const chrono::time_point<_
return static_cast<unsigned long>(_Rel_time.count());
}

inline constexpr ptrdiff_t _Semaphore_max = (1ULL << (sizeof(ptrdiff_t) * CHAR_BIT - 1)) - 1;
inline constexpr ptrdiff_t _Semaphore_max = PTRDIFF_MAX;

_EXPORT_STD template <ptrdiff_t _Least_max_value = _Semaphore_max>
class counting_semaphore {
Expand Down