From 942c4b32b0553378f843e606bb56c417acbdc4be Mon Sep 17 00:00:00 2001 From: Thomas Rodgers Date: Fri, 15 Nov 2019 03:09:19 +0000 Subject: Support for jthread and stop_token * include/Makefile.am: Add header. * include/Makefile.in: Regenerate. * include/std/condition_variable: Add overloads for stop_token support to condition_variable_any. * include/std/stop_token: New file. * include/std/thread: Add jthread type. * include/std/version (__cpp_lib_jthread): New value. * testsuite/30_threads/condition_variable_any/stop_token/1.cc: New test. * testsuite/30_threads/condition_variable_any/stop_token/2.cc: New test. * testsuite/30_threads/condition_variable_any/stop_token/wait_on.cc: New test. * testsuite/30_threads/jthread/1.cc: New test. * testsuite/30_threads/jthread/2.cc: New test. * testsuite/30_threads/jthread/jthread.cc: New test. * testsuite/30_threads/stop_token/1.cc: New test. * testsuite/30_threads/stop_token/2.cc: New test. * testsuite/30_threads/stop_token/stop_token.cc: New test. From-SVN: r278274 --- libstdc++-v3/include/std/condition_variable | 84 +++++++++++++++++++++++++++++ 1 file changed, 84 insertions(+) (limited to 'libstdc++-v3/include/std/condition_variable') diff --git a/libstdc++-v3/include/std/condition_variable b/libstdc++-v3/include/std/condition_variable index cc96661e94c..8887cee29fa 100644 --- a/libstdc++-v3/include/std/condition_variable +++ b/libstdc++-v3/include/std/condition_variable @@ -36,6 +36,7 @@ #else #include + #include #include #include @@ -45,6 +46,11 @@ #include #include +#if __cplusplus > 201703L +#define __cpp_lib_jthread 201907L +#include +#endif + #if defined(_GLIBCXX_HAS_GTHREADS) namespace std _GLIBCXX_VISIBILITY(default) @@ -360,6 +366,84 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION wait_for(_Lock& __lock, const chrono::duration<_Rep, _Period>& __rtime, _Predicate __p) { return wait_until(__lock, __clock_t::now() + __rtime, std::move(__p)); } + +#ifdef __cpp_lib_jthread + template + bool wait_on(_Lock& __lock, + stop_token __stoken, + _Predicate __p) + { + if (__stoken.stop_requested()) + { + return __p(); + } + + std::stop_callback __cb(__stoken, [this] { notify_all(); }); + shared_ptr __mutex = _M_mutex; + while (!__p()) + { + unique_lock __my_lock(*__mutex); + if (__stoken.stop_requested()) + { + return false; + } + // *__mutex must be unlocked before re-locking __lock so move + // ownership of *__mutex lock to an object with shorter lifetime. + _Unlock<_Lock> __unlock(__lock); + unique_lock __my_lock2(std::move(__my_lock)); + _M_cond.wait(__my_lock2); + } + return true; + } + + template + bool wait_on_until(_Lock& __lock, + stop_token __stoken, + const chrono::time_point<_Clock, _Duration>& __abs_time, + _Predicate __p) + { + if (__stoken.stop_requested()) + { + return __p(); + } + + std::stop_callback __cb(__stoken, [this] { notify_all(); }); + shared_ptr __mutex = _M_mutex; + while (!__p()) + { + bool __stop; + { + unique_lock __my_lock(*__mutex); + if (__stoken.stop_requested()) + { + return false; + } + _Unlock<_Lock> __u(__lock); + unique_lock __my_lock2(std::move(__my_lock)); + const auto __status = _M_cond.wait_until(__my_lock2, __abs_time); + __stop = (__status == std::cv_status::timeout) || __stoken.stop_requested(); + } + if (__stop) + { + return __p(); + } + } + return true; + } + + template + bool wait_on_for(_Lock& __lock, + stop_token __stoken, + const chrono::duration<_Rep, _Period>& __rel_time, + _Predicate __p) + { + auto __abst = std::chrono::steady_clock::now() + __rel_time; + return wait_on_until(__lock, + std::move(__stoken), + __abst, + std::move(__p)); + } +#endif }; } // end inline namespace -- cgit v1.2.1