Skip to content

Commit 4fa812b

Browse files
committed
[libc++] Implement std::condition_variable_any::wait[_for/until] overloads that take stop_token
- This is section 32.6.4 of P0660R10 - https://eel.is/c++draft/thread.condvarany.intwait Differential Revision: https://reviews.llvm.org/D153441
1 parent a806aef commit 4fa812b

24 files changed

+630
-44
lines changed

libcxx/docs/FeatureTestMacroTable.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -252,7 +252,7 @@ Status
252252
--------------------------------------------------- -----------------
253253
``__cpp_lib_is_pointer_interconvertible`` *unimplemented*
254254
--------------------------------------------------- -----------------
255-
``__cpp_lib_jthread`` *unimplemented*
255+
``__cpp_lib_jthread`` ``201911L``
256256
--------------------------------------------------- -----------------
257257
``__cpp_lib_latch`` ``201907L``
258258
--------------------------------------------------- -----------------

libcxx/docs/Status/Cxx20.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ Paper Status
4848
.. [#note-P0883.1] P0883: shared_ptr and floating-point changes weren't applied as they themselves aren't implemented yet.
4949
.. [#note-P0883.2] P0883: ``ATOMIC_FLAG_INIT`` was marked deprecated in version 14.0, but was undeprecated with the implementation of LWG3659 in version 15.0.
5050
.. [#note-P2231] P2231: Optional is complete. The changes to variant haven't been implemented yet.
51-
.. [#note-P0660] P0660: Section 32.3 Stop Tokens is complete. ``jthread`` hasn't been implemented yet.
51+
.. [#note-P0660] P0660: The paper is implemented but the features are experimental and can be enabled via ``-fexperimental-library``.
5252
.. [#note-P0355] P0355: The implementation status is:
5353
5454
* ``Calendars`` mostly done in Clang 7

libcxx/docs/Status/Cxx20Papers.csv

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@
104104
"`P0553R4 <https://wg21.link/P0553R4>`__","LWG","Bit operations","Cologne","|Complete|","9.0"
105105
"`P0631R8 <https://wg21.link/P0631R8>`__","LWG","Math Constants","Cologne","|Complete|","11.0"
106106
"`P0645R10 <https://wg21.link/P0645R10>`__","LWG","Text Formatting","Cologne","|Complete| [#note-P0645]_","14.0"
107-
"`P0660R10 <https://wg21.link/P0660R10>`__","LWG","Stop Token and Joining Thread, Rev 10.","Cologne","|In Progress| [#note-P0660]_",""
107+
"`P0660R10 <https://wg21.link/P0660R10>`__","LWG","Stop Token and Joining Thread, Rev 10.","Cologne","|Complete| [#note-P0660]_","18.0.0"
108108
"`P0784R7 <https://wg21.link/P0784R7>`__","CWG","More constexpr containers","Cologne","|Complete|","12.0"
109109
"`P0980R1 <https://wg21.link/P0980R1>`__","LWG","Making std::string constexpr","Cologne","|Complete|","15.0"
110110
"`P1004R2 <https://wg21.link/P1004R2>`__","LWG","Making std::vector constexpr","Cologne","|Complete|","15.0"

libcxx/include/__stop_token/stop_callback.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ _LIBCPP_PUSH_MACROS
3131

3232
_LIBCPP_BEGIN_NAMESPACE_STD
3333

34-
#if _LIBCPP_STD_VER >= 20 && !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_STOP_TOKEN)
34+
#if _LIBCPP_STD_VER >= 20 && !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_STOP_TOKEN) && !defined(_LIBCPP_HAS_NO_THREADS)
3535

3636
template <class _Callback>
3737
class _LIBCPP_AVAILABILITY_SYNC stop_callback : private __stop_callback_base {
@@ -101,4 +101,4 @@ _LIBCPP_END_NAMESPACE_STD
101101

102102
_LIBCPP_POP_MACROS
103103

104-
#endif // _LIBCPP_STD_VER >= 20 && !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_STOP_TOKEN)
104+
#endif // _LIBCPP_STD_VER >= 20 && !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_STOP_TOKEN) && !defined(_LIBCPP_HAS_NO_THREADS)

libcxx/include/__stop_token/stop_source.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323

2424
_LIBCPP_BEGIN_NAMESPACE_STD
2525

26-
#if _LIBCPP_STD_VER >= 20 && !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_STOP_TOKEN)
26+
#if _LIBCPP_STD_VER >= 20 && !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_STOP_TOKEN) && !defined(_LIBCPP_HAS_NO_THREADS)
2727

2828
struct nostopstate_t {
2929
explicit nostopstate_t() = default;
@@ -89,4 +89,4 @@ class _LIBCPP_AVAILABILITY_SYNC stop_source {
8989

9090
_LIBCPP_END_NAMESPACE_STD
9191

92-
#endif // _LIBCPP_STD_VER >= 20 && !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_STOP_TOKEN)
92+
#endif // _LIBCPP_STD_VER >= 20 && !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_STOP_TOKEN) && !defined(_LIBCPP_HAS_NO_THREADS)

libcxx/include/__stop_token/stop_state.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424

2525
_LIBCPP_BEGIN_NAMESPACE_STD
2626

27-
#if _LIBCPP_STD_VER >= 20
27+
#if _LIBCPP_STD_VER >= 20 && !defined(_LIBCPP_HAS_NO_THREADS)
2828

2929
struct __stop_callback_base : __intrusive_node_base<__stop_callback_base> {
3030
using __callback_fn_t = void(__stop_callback_base*) noexcept;
@@ -229,7 +229,7 @@ struct __intrusive_shared_ptr_traits<__stop_state> {
229229
}
230230
};
231231

232-
#endif // _LIBCPP_STD_VER >= 20
232+
#endif // _LIBCPP_STD_VER >= 20 && !defined(_LIBCPP_HAS_NO_THREADS)
233233

234234
_LIBCPP_END_NAMESPACE_STD
235235

libcxx/include/__stop_token/stop_token.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121

2222
_LIBCPP_BEGIN_NAMESPACE_STD
2323

24-
#if _LIBCPP_STD_VER >= 20 && !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_STOP_TOKEN)
24+
#if _LIBCPP_STD_VER >= 20 && !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_STOP_TOKEN) && !defined(_LIBCPP_HAS_NO_THREADS)
2525

2626
class _LIBCPP_AVAILABILITY_SYNC stop_token {
2727
public:
@@ -57,7 +57,7 @@ class _LIBCPP_AVAILABILITY_SYNC stop_token {
5757
_LIBCPP_HIDE_FROM_ABI explicit stop_token(const __intrusive_shared_ptr<__stop_state>& __state) : __state_(__state) {}
5858
};
5959

60-
#endif // _LIBCPP_STD_VER >= 20 && !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_STOP_TOKEN)
60+
#endif // _LIBCPP_STD_VER >= 20 && !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_STOP_TOKEN) && !defined(_LIBCPP_HAS_NO_THREADS)
6161

6262
_LIBCPP_END_NAMESPACE_STD
6363

libcxx/include/condition_variable

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,13 +100,26 @@ public:
100100
wait_for(Lock& lock,
101101
const chrono::duration<Rep, Period>& rel_time,
102102
Predicate pred);
103+
104+
// [thread.condvarany.intwait], interruptible waits
105+
template <class Lock, class Predicate>
106+
bool wait(Lock& lock, stop_token stoken, Predicate pred); // since C++20
107+
108+
template <class Lock, class Clock, class Duration, class Predicate>
109+
bool wait_until(Lock& lock, stop_token stoken,
110+
const chrono::time_point<Clock, Duration>& abs_time, Predicate pred); // since C++20
111+
112+
template <class Lock, class Rep, class Period, class Predicate>
113+
bool wait_for(Lock& lock, stop_token stoken,
114+
const chrono::duration<Rep, Period>& rel_time, Predicate pred); // since C++20
103115
};
104116
105117
} // std
106118
107119
*/
108120

109121
#include <__assert> // all public C++ headers provide the assertion handler
122+
#include <__availability>
110123
#include <__chrono/duration.h>
111124
#include <__chrono/steady_clock.h>
112125
#include <__chrono/time_point.h>
@@ -118,6 +131,7 @@ public:
118131
#include <__mutex/mutex.h>
119132
#include <__mutex/tag_types.h>
120133
#include <__mutex/unique_lock.h>
134+
#include <__stop_token/stop_token.h>
121135
#include <__utility/move.h>
122136
#include <version>
123137

@@ -174,6 +188,21 @@ public:
174188
wait_for(_Lock& __lock,
175189
const chrono::duration<_Rep, _Period>& __d,
176190
_Predicate __pred);
191+
192+
#if _LIBCPP_STD_VER >= 20 && !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_STOP_TOKEN)
193+
194+
template <class _Lock, class _Predicate>
195+
_LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI bool wait(_Lock& __lock, stop_token __stoken, _Predicate __pred);
196+
197+
template <class _Lock, class _Clock, class _Duration, class _Predicate>
198+
_LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI bool wait_until(_Lock& __lock, stop_token __stoken,
199+
const chrono::time_point<_Clock, _Duration>& __abs_time, _Predicate __pred);
200+
201+
template <class _Lock, class _Rep, class _Period, class _Predicate>
202+
_LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI bool wait_for(_Lock& __lock, stop_token __stoken,
203+
const chrono::duration<_Rep, _Period>& __rel_time, _Predicate __pred);
204+
205+
#endif // _LIBCPP_STD_VER >= 20 && !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_STOP_TOKEN)
177206
};
178207

179208
inline
@@ -269,6 +298,38 @@ condition_variable_any::wait_for(_Lock& __lock,
269298
_VSTD::move(__pred));
270299
}
271300

301+
#if _LIBCPP_STD_VER >= 20 && !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_STOP_TOKEN)
302+
303+
template <class _Lock, class _Predicate>
304+
bool condition_variable_any::wait(_Lock& __lock, stop_token __stoken, _Predicate __pred) {
305+
while (!__stoken.stop_requested()) {
306+
if (__pred())
307+
return true;
308+
wait(__lock);
309+
}
310+
return __pred();
311+
}
312+
313+
template <class _Lock, class _Clock, class _Duration, class _Predicate>
314+
bool condition_variable_any::wait_until(
315+
_Lock& __lock, stop_token __stoken, const chrono::time_point<_Clock, _Duration>& __abs_time, _Predicate __pred) {
316+
while (!__stoken.stop_requested()) {
317+
if (__pred())
318+
return true;
319+
if (wait_until(__lock, __abs_time) == cv_status::timeout)
320+
return __pred();
321+
}
322+
return __pred();
323+
}
324+
325+
template <class _Lock, class _Rep, class _Period, class _Predicate>
326+
bool condition_variable_any::wait_for(
327+
_Lock& __lock, stop_token __stoken, const chrono::duration<_Rep, _Period>& __rel_time, _Predicate __pred) {
328+
return wait_until(__lock, std::move(__stoken), chrono::steady_clock::now() + __rel_time, std::move(__pred));
329+
}
330+
331+
#endif // _LIBCPP_STD_VER >= 20 && !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_STOP_TOKEN)
332+
272333
_LIBCPP_EXPORTED_FROM_ABI void notify_all_at_thread_exit(condition_variable&, unique_lock<mutex>);
273334

274335
_LIBCPP_END_NAMESPACE_STD

libcxx/include/version

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -372,8 +372,8 @@ __cpp_lib_within_lifetime 202306L <type_traits>
372372
// # define __cpp_lib_is_layout_compatible 201907L
373373
# define __cpp_lib_is_nothrow_convertible 201806L
374374
// # define __cpp_lib_is_pointer_interconvertible 201907L
375-
# if !defined(_LIBCPP_HAS_NO_THREADS)
376-
// # define __cpp_lib_jthread 201911L
375+
# if !defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_STOP_TOKEN) && !defined(_LIBCPP_AVAILABILITY_HAS_NO_SYNC)
376+
# define __cpp_lib_jthread 201911L
377377
# endif
378378
# if !defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_AVAILABILITY_HAS_NO_SYNC)
379379
# define __cpp_lib_latch 201907L

libcxx/test/libcxx/transitive_includes/cxx03.csv

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,7 @@ condition_variable cstdlib
175175
condition_variable cstring
176176
condition_variable ctime
177177
condition_variable initializer_list
178+
condition_variable iosfwd
178179
condition_variable limits
179180
condition_variable new
180181
condition_variable ratio

0 commit comments

Comments
 (0)