From a4293c83a270cf3e1a0ec59ddee3b8ce20e2af20 Mon Sep 17 00:00:00 2001 From: cpplearner Date: Tue, 23 Feb 2021 16:53:42 +0800 Subject: [PATCH 1/4] Enforce is_clock_v in [thread] headers --- stl/inc/condition_variable | 9 +++++++++ stl/inc/future | 3 +++ stl/inc/mutex | 30 +++++++++++++++++++++++++----- stl/inc/semaphore | 2 ++ stl/inc/shared_mutex | 32 ++++++++++++++++++++++---------- stl/inc/thread | 3 +++ 6 files changed, 64 insertions(+), 15 deletions(-) diff --git a/stl/inc/condition_variable b/stl/inc/condition_variable index 42d02aa8db7..19721bed8ce 100644 --- a/stl/inc/condition_variable +++ b/stl/inc/condition_variable @@ -92,12 +92,18 @@ public: template cv_status wait_until(_Lock& _Lck, const chrono::time_point<_Clock, _Duration>& _Abs_time) { // wait until time point +#if _HAS_CXX20 + static_assert(is_clock_v<_Clock>, "Clock type required"); +#endif // _HAS_CXX20 return wait_for(_Lck, _Abs_time - _Clock::now()); } template bool wait_until(_Lock& _Lck, const chrono::time_point<_Clock, _Duration>& _Abs_time, _Predicate _Pred) { // wait for signal with timeout and check predicate +#if _HAS_CXX20 + static_assert(is_clock_v<_Clock>, "Clock type required"); +#endif // _HAS_CXX20 while (!_Pred()) { if (wait_until(_Lck, _Abs_time) == cv_status::timeout) { return _Pred(); @@ -193,6 +199,9 @@ public: template bool wait_until( _Lock& _Lck, stop_token _Stoken, const chrono::time_point<_Clock, _Duration>& _Abs_time, _Predicate _Pred) { +#if _HAS_CXX20 + static_assert(is_clock_v<_Clock>, "Clock type required"); +#endif // _HAS_CXX20 stop_callback<_Cv_any_notify_all> _Cb{_Stoken, this}; for (;;) { if (_Pred()) { diff --git a/stl/inc/future b/stl/inc/future index d38072b6692..0173d72dc01 100644 --- a/stl/inc/future +++ b/stl/inc/future @@ -770,6 +770,9 @@ public: template future_status wait_until(const chrono::time_point<_Clock, _Dur>& _Abs_time) const { // wait until time point +#if _HAS_CXX20 + static_assert(is_clock_v<_Clock>, "Clock type required"); +#endif // _HAS_CXX20 if (!valid()) { _Throw_future_error(make_error_code(future_errc::no_state)); } diff --git a/stl/inc/mutex b/stl/inc/mutex index cf58b283725..7d22905f95a 100644 --- a/stl/inc/mutex +++ b/stl/inc/mutex @@ -153,7 +153,12 @@ public: template _NODISCARD_CTOR unique_lock(_Mutex& _Mtx, const chrono::time_point<_Clock, _Duration>& _Abs_time) - : _Pmtx(_STD addressof(_Mtx)), _Owns(_Pmtx->try_lock_until(_Abs_time)) {} // construct and lock with timeout + : _Pmtx(_STD addressof(_Mtx)), _Owns(_Pmtx->try_lock_until(_Abs_time)) { + // construct and lock with timeout +#if _HAS_CXX20 + static_assert(is_clock_v<_Clock>, "Clock type required"); +#endif // _HAS_CXX20 + } _NODISCARD_CTOR unique_lock(_Mutex& _Mtx, const xtime* _Abs_time) : _Pmtx(_STD addressof(_Mtx)), _Owns(false) { // try to lock until _Abs_time @@ -209,6 +214,9 @@ public: template _NODISCARD bool try_lock_until(const chrono::time_point<_Clock, _Duration>& _Abs_time) { +#if _HAS_CXX20 + static_assert(is_clock_v<_Clock>, "Clock type required"); +#endif // _HAS_CXX20 _Validate(); _Owns = _Pmtx->try_lock_until(_Abs_time); return _Owns; @@ -635,6 +643,9 @@ public: template cv_status wait_until(unique_lock& _Lck, const chrono::time_point<_Clock, _Duration>& _Abs_time) { // wait until time point +#if _HAS_CXX20 + static_assert(is_clock_v<_Clock>, "Clock type required"); +#endif // _HAS_CXX20 for (;;) { const auto _Now = _Clock::now(); if (_Abs_time <= _Now) { @@ -654,6 +665,9 @@ public: bool wait_until( unique_lock& _Lck, const chrono::time_point<_Clock, _Duration>& _Abs_time, _Predicate _Pred) { // wait for signal with timeout and check predicate +#if _HAS_CXX20 + static_assert(is_clock_v<_Clock>, "Clock type required"); +#endif // _HAS_CXX20 return _Wait_until1(_Lck, _Abs_time, _Pred); } @@ -792,8 +806,11 @@ public: } template - _NODISCARD bool try_lock_until( - const chrono::time_point<_Clock, _Duration>& _Abs_time) { // try to lock the mutex with timeout + _NODISCARD bool try_lock_until(const chrono::time_point<_Clock, _Duration>& _Abs_time) { + // try to lock the mutex with timeout +#if _HAS_CXX20 + static_assert(is_clock_v<_Clock>, "Clock type required"); +#endif // _HAS_CXX20 return _Try_lock_until(_Abs_time); } @@ -903,8 +920,11 @@ public: } template - _NODISCARD bool try_lock_until( - const chrono::time_point<_Clock, _Duration>& _Abs_time) { // try to lock the mutex with timeout + _NODISCARD bool try_lock_until(const chrono::time_point<_Clock, _Duration>& _Abs_time) { + // try to lock the mutex with timeout +#if _HAS_CXX20 + static_assert(is_clock_v<_Clock>, "Clock type required"); +#endif // _HAS_CXX20 return _Try_lock_until(_Abs_time); } diff --git a/stl/inc/semaphore b/stl/inc/semaphore index 79d2760603b..5b5f266ef93 100644 --- a/stl/inc/semaphore +++ b/stl/inc/semaphore @@ -177,6 +177,7 @@ public: template _NODISCARD bool try_acquire_until(const chrono::time_point<_Clock, _Duration>& _Abs_time) { + static_assert(is_clock_v<_Clock>, "Clock type required"); ptrdiff_t _Current = _Counter.load(memory_order_relaxed); for (;;) { while (_Current == 0) { @@ -274,6 +275,7 @@ public: template _NODISCARD bool try_acquire_until(const chrono::time_point<_Clock, _Duration>& _Abs_time) { + static_assert(is_clock_v<_Clock>, "Clock type required"); for (;;) { // "happens after release" ordering is provided by this exchange, so loads and waits can be relaxed // TRANSITION, GH-1133: should be memory_order_acquire diff --git a/stl/inc/shared_mutex b/stl/inc/shared_mutex index 4509b0cb62b..790f26641eb 100644 --- a/stl/inc/shared_mutex +++ b/stl/inc/shared_mutex @@ -114,8 +114,11 @@ public: } template - _NODISCARD bool try_lock_until( - const chrono::time_point<_Clock, _Duration>& _Abs_time) { // try to lock until time point + _NODISCARD bool try_lock_until(const chrono::time_point<_Clock, _Duration>& _Abs_time) { + // try to lock until time point +#if _HAS_CXX20 + static_assert(is_clock_v<_Clock>, "Clock type required"); +#endif // _HAS_CXX20 auto _Not_writing = [this] { return !_Writing; }; auto _Zero_readers = [this] { return _Readers == 0; }; unique_lock _Lock(_Mymtx); @@ -166,8 +169,8 @@ public: } template - _NODISCARD bool try_lock_shared_for( - const chrono::duration<_Rep, _Period>& _Rel_time) { // try to lock non-exclusive for relative time + _NODISCARD bool try_lock_shared_for(const chrono::duration<_Rep, _Period>& _Rel_time) { + // try to lock non-exclusive for relative time return try_lock_shared_until(_To_absolute_time(_Rel_time)); } @@ -186,8 +189,11 @@ public: } template - _NODISCARD bool try_lock_shared_until( - const chrono::time_point<_Clock, _Duration>& _Abs_time) { // try to lock non-exclusive until absolute time + _NODISCARD bool try_lock_shared_until(const chrono::time_point<_Clock, _Duration>& _Abs_time) { + // try to lock non-exclusive until absolute time +#if _HAS_CXX20 + static_assert(is_clock_v<_Clock>, "Clock type required"); +#endif // _HAS_CXX20 return _Try_lock_shared_until(_Abs_time); } @@ -257,6 +263,9 @@ public: _NODISCARD_CTOR shared_lock(mutex_type& _Mtx, const chrono::time_point<_Clock, _Duration>& _Abs_time) : _Pmtx(_STD addressof(_Mtx)), _Owns(_Mtx.try_lock_shared_until(_Abs_time)) { // construct with mutex and try to lock until absolute time +#if _HAS_CXX20 + static_assert(is_clock_v<_Clock>, "Clock type required"); +#endif // _HAS_CXX20 } ~shared_lock() noexcept { @@ -298,16 +307,19 @@ public: } template - _NODISCARD bool try_lock_for( - const chrono::duration<_Rep, _Period>& _Rel_time) { // try to lock the mutex for _Rel_time + _NODISCARD bool try_lock_for(const chrono::duration<_Rep, _Period>& _Rel_time) { + // try to lock the mutex for _Rel_time _Validate(); _Owns = _Pmtx->try_lock_shared_for(_Rel_time); return _Owns; } template - _NODISCARD bool try_lock_until( - const chrono::time_point<_Clock, _Duration>& _Abs_time) { // try to lock the mutex until _Abs_time + _NODISCARD bool try_lock_until(const chrono::time_point<_Clock, _Duration>& _Abs_time) { + // try to lock the mutex until _Abs_time +#if _HAS_CXX20 + static_assert(is_clock_v<_Clock>, "Clock type required"); +#endif // _HAS_CXX20 _Validate(); _Owns = _Pmtx->try_lock_shared_until(_Abs_time); return _Owns; diff --git a/stl/inc/thread b/stl/inc/thread index 2d46b78936d..5d4cf62b6be 100644 --- a/stl/inc/thread +++ b/stl/inc/thread @@ -185,6 +185,9 @@ namespace this_thread { template void sleep_until(const chrono::time_point<_Clock, _Duration>& _Abs_time) { +#if _HAS_CXX20 + static_assert(is_clock_v<_Clock>, "Clock type required"); +#endif // _HAS_CXX20 for (;;) { const auto _Now = _Clock::now(); if (_Abs_time <= _Now) { From 70051e75f8ad8eccc99363ca10871f4cd746d412 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Tue, 23 Feb 2021 02:49:26 -0800 Subject: [PATCH 2/4] clang-format. --- stl/inc/mutex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stl/inc/mutex b/stl/inc/mutex index 7d22905f95a..244383213b9 100644 --- a/stl/inc/mutex +++ b/stl/inc/mutex @@ -158,7 +158,7 @@ public: #if _HAS_CXX20 static_assert(is_clock_v<_Clock>, "Clock type required"); #endif // _HAS_CXX20 - } + } _NODISCARD_CTOR unique_lock(_Mutex& _Mtx, const xtime* _Abs_time) : _Pmtx(_STD addressof(_Mtx)), _Owns(false) { // try to lock until _Abs_time From 203c6b9eb53fe9ff70f11ba8a341f763e0e79397 Mon Sep 17 00:00:00 2001 From: cpplearner Date: Tue, 23 Feb 2021 20:02:14 +0800 Subject: [PATCH 3/4] Fix --- stl/inc/condition_variable | 6 +++--- stl/inc/future | 2 +- stl/inc/mutex | 12 ++++++------ stl/inc/semaphore | 4 ++-- stl/inc/shared_mutex | 8 ++++---- stl/inc/thread | 2 +- 6 files changed, 17 insertions(+), 17 deletions(-) diff --git a/stl/inc/condition_variable b/stl/inc/condition_variable index 19721bed8ce..304c7a9b3fa 100644 --- a/stl/inc/condition_variable +++ b/stl/inc/condition_variable @@ -93,7 +93,7 @@ public: cv_status wait_until(_Lock& _Lck, const chrono::time_point<_Clock, _Duration>& _Abs_time) { // wait until time point #if _HAS_CXX20 - static_assert(is_clock_v<_Clock>, "Clock type required"); + static_assert(chrono::is_clock_v<_Clock>, "Clock type required"); #endif // _HAS_CXX20 return wait_for(_Lck, _Abs_time - _Clock::now()); } @@ -102,7 +102,7 @@ public: bool wait_until(_Lock& _Lck, const chrono::time_point<_Clock, _Duration>& _Abs_time, _Predicate _Pred) { // wait for signal with timeout and check predicate #if _HAS_CXX20 - static_assert(is_clock_v<_Clock>, "Clock type required"); + static_assert(chrono::is_clock_v<_Clock>, "Clock type required"); #endif // _HAS_CXX20 while (!_Pred()) { if (wait_until(_Lck, _Abs_time) == cv_status::timeout) { @@ -200,7 +200,7 @@ public: bool wait_until( _Lock& _Lck, stop_token _Stoken, const chrono::time_point<_Clock, _Duration>& _Abs_time, _Predicate _Pred) { #if _HAS_CXX20 - static_assert(is_clock_v<_Clock>, "Clock type required"); + static_assert(chrono::is_clock_v<_Clock>, "Clock type required"); #endif // _HAS_CXX20 stop_callback<_Cv_any_notify_all> _Cb{_Stoken, this}; for (;;) { diff --git a/stl/inc/future b/stl/inc/future index 0173d72dc01..3036d53dd0b 100644 --- a/stl/inc/future +++ b/stl/inc/future @@ -771,7 +771,7 @@ public: template future_status wait_until(const chrono::time_point<_Clock, _Dur>& _Abs_time) const { // wait until time point #if _HAS_CXX20 - static_assert(is_clock_v<_Clock>, "Clock type required"); + static_assert(chrono::is_clock_v<_Clock>, "Clock type required"); #endif // _HAS_CXX20 if (!valid()) { _Throw_future_error(make_error_code(future_errc::no_state)); diff --git a/stl/inc/mutex b/stl/inc/mutex index 244383213b9..aafefe48bcd 100644 --- a/stl/inc/mutex +++ b/stl/inc/mutex @@ -156,7 +156,7 @@ public: : _Pmtx(_STD addressof(_Mtx)), _Owns(_Pmtx->try_lock_until(_Abs_time)) { // construct and lock with timeout #if _HAS_CXX20 - static_assert(is_clock_v<_Clock>, "Clock type required"); + static_assert(chrono::is_clock_v<_Clock>, "Clock type required"); #endif // _HAS_CXX20 } @@ -215,7 +215,7 @@ public: template _NODISCARD bool try_lock_until(const chrono::time_point<_Clock, _Duration>& _Abs_time) { #if _HAS_CXX20 - static_assert(is_clock_v<_Clock>, "Clock type required"); + static_assert(chrono::is_clock_v<_Clock>, "Clock type required"); #endif // _HAS_CXX20 _Validate(); _Owns = _Pmtx->try_lock_until(_Abs_time); @@ -644,7 +644,7 @@ public: cv_status wait_until(unique_lock& _Lck, const chrono::time_point<_Clock, _Duration>& _Abs_time) { // wait until time point #if _HAS_CXX20 - static_assert(is_clock_v<_Clock>, "Clock type required"); + static_assert(chrono::is_clock_v<_Clock>, "Clock type required"); #endif // _HAS_CXX20 for (;;) { const auto _Now = _Clock::now(); @@ -666,7 +666,7 @@ public: unique_lock& _Lck, const chrono::time_point<_Clock, _Duration>& _Abs_time, _Predicate _Pred) { // wait for signal with timeout and check predicate #if _HAS_CXX20 - static_assert(is_clock_v<_Clock>, "Clock type required"); + static_assert(chrono::is_clock_v<_Clock>, "Clock type required"); #endif // _HAS_CXX20 return _Wait_until1(_Lck, _Abs_time, _Pred); } @@ -809,7 +809,7 @@ public: _NODISCARD bool try_lock_until(const chrono::time_point<_Clock, _Duration>& _Abs_time) { // try to lock the mutex with timeout #if _HAS_CXX20 - static_assert(is_clock_v<_Clock>, "Clock type required"); + static_assert(chrono::is_clock_v<_Clock>, "Clock type required"); #endif // _HAS_CXX20 return _Try_lock_until(_Abs_time); } @@ -923,7 +923,7 @@ public: _NODISCARD bool try_lock_until(const chrono::time_point<_Clock, _Duration>& _Abs_time) { // try to lock the mutex with timeout #if _HAS_CXX20 - static_assert(is_clock_v<_Clock>, "Clock type required"); + static_assert(chrono::is_clock_v<_Clock>, "Clock type required"); #endif // _HAS_CXX20 return _Try_lock_until(_Abs_time); } diff --git a/stl/inc/semaphore b/stl/inc/semaphore index 5b5f266ef93..903c4800bdd 100644 --- a/stl/inc/semaphore +++ b/stl/inc/semaphore @@ -177,7 +177,7 @@ public: template _NODISCARD bool try_acquire_until(const chrono::time_point<_Clock, _Duration>& _Abs_time) { - static_assert(is_clock_v<_Clock>, "Clock type required"); + static_assert(chrono::is_clock_v<_Clock>, "Clock type required"); ptrdiff_t _Current = _Counter.load(memory_order_relaxed); for (;;) { while (_Current == 0) { @@ -275,7 +275,7 @@ public: template _NODISCARD bool try_acquire_until(const chrono::time_point<_Clock, _Duration>& _Abs_time) { - static_assert(is_clock_v<_Clock>, "Clock type required"); + static_assert(chrono::is_clock_v<_Clock>, "Clock type required"); for (;;) { // "happens after release" ordering is provided by this exchange, so loads and waits can be relaxed // TRANSITION, GH-1133: should be memory_order_acquire diff --git a/stl/inc/shared_mutex b/stl/inc/shared_mutex index 790f26641eb..a735ca0938c 100644 --- a/stl/inc/shared_mutex +++ b/stl/inc/shared_mutex @@ -117,7 +117,7 @@ public: _NODISCARD bool try_lock_until(const chrono::time_point<_Clock, _Duration>& _Abs_time) { // try to lock until time point #if _HAS_CXX20 - static_assert(is_clock_v<_Clock>, "Clock type required"); + static_assert(chrono::is_clock_v<_Clock>, "Clock type required"); #endif // _HAS_CXX20 auto _Not_writing = [this] { return !_Writing; }; auto _Zero_readers = [this] { return _Readers == 0; }; @@ -192,7 +192,7 @@ public: _NODISCARD bool try_lock_shared_until(const chrono::time_point<_Clock, _Duration>& _Abs_time) { // try to lock non-exclusive until absolute time #if _HAS_CXX20 - static_assert(is_clock_v<_Clock>, "Clock type required"); + static_assert(chrono::is_clock_v<_Clock>, "Clock type required"); #endif // _HAS_CXX20 return _Try_lock_shared_until(_Abs_time); } @@ -264,7 +264,7 @@ public: : _Pmtx(_STD addressof(_Mtx)), _Owns(_Mtx.try_lock_shared_until(_Abs_time)) { // construct with mutex and try to lock until absolute time #if _HAS_CXX20 - static_assert(is_clock_v<_Clock>, "Clock type required"); + static_assert(chrono::is_clock_v<_Clock>, "Clock type required"); #endif // _HAS_CXX20 } @@ -318,7 +318,7 @@ public: _NODISCARD bool try_lock_until(const chrono::time_point<_Clock, _Duration>& _Abs_time) { // try to lock the mutex until _Abs_time #if _HAS_CXX20 - static_assert(is_clock_v<_Clock>, "Clock type required"); + static_assert(chrono::is_clock_v<_Clock>, "Clock type required"); #endif // _HAS_CXX20 _Validate(); _Owns = _Pmtx->try_lock_shared_until(_Abs_time); diff --git a/stl/inc/thread b/stl/inc/thread index 5d4cf62b6be..92bf3c8d83e 100644 --- a/stl/inc/thread +++ b/stl/inc/thread @@ -186,7 +186,7 @@ namespace this_thread { template void sleep_until(const chrono::time_point<_Clock, _Duration>& _Abs_time) { #if _HAS_CXX20 - static_assert(is_clock_v<_Clock>, "Clock type required"); + static_assert(chrono::is_clock_v<_Clock>, "Clock type required"); #endif // _HAS_CXX20 for (;;) { const auto _Now = _Clock::now(); From 15b07f7ab56469f3cab25e8b73ec582148a3af62 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Tue, 2 Mar 2021 00:22:26 -0800 Subject: [PATCH 4/4] wait_until(args, stop_token, args) is C++20. --- stl/inc/condition_variable | 2 -- 1 file changed, 2 deletions(-) diff --git a/stl/inc/condition_variable b/stl/inc/condition_variable index 304c7a9b3fa..3c17c8227a3 100644 --- a/stl/inc/condition_variable +++ b/stl/inc/condition_variable @@ -199,9 +199,7 @@ public: template bool wait_until( _Lock& _Lck, stop_token _Stoken, const chrono::time_point<_Clock, _Duration>& _Abs_time, _Predicate _Pred) { -#if _HAS_CXX20 static_assert(chrono::is_clock_v<_Clock>, "Clock type required"); -#endif // _HAS_CXX20 stop_callback<_Cv_any_notify_all> _Cb{_Stoken, this}; for (;;) { if (_Pred()) {