Skip to content

Commit

Permalink
[libc++] Implement std::condition_variable_any::wait[_for/until] ov…
Browse files Browse the repository at this point in the history
…erloads 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
  • Loading branch information
huixie90 committed Sep 29, 2023
1 parent a806aef commit 4fa812b
Show file tree
Hide file tree
Showing 24 changed files with 630 additions and 44 deletions.
2 changes: 1 addition & 1 deletion libcxx/docs/FeatureTestMacroTable.rst
Original file line number Diff line number Diff line change
Expand Up @@ -252,7 +252,7 @@ Status
--------------------------------------------------- -----------------
``__cpp_lib_is_pointer_interconvertible`` *unimplemented*
--------------------------------------------------- -----------------
``__cpp_lib_jthread`` *unimplemented*
``__cpp_lib_jthread`` ``201911L``
--------------------------------------------------- -----------------
``__cpp_lib_latch`` ``201907L``
--------------------------------------------------- -----------------
Expand Down
2 changes: 1 addition & 1 deletion libcxx/docs/Status/Cxx20.rst
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ Paper Status
.. [#note-P0883.1] P0883: shared_ptr and floating-point changes weren't applied as they themselves aren't implemented yet.
.. [#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.
.. [#note-P2231] P2231: Optional is complete. The changes to variant haven't been implemented yet.
.. [#note-P0660] P0660: Section 32.3 Stop Tokens is complete. ``jthread`` hasn't been implemented yet.
.. [#note-P0660] P0660: The paper is implemented but the features are experimental and can be enabled via ``-fexperimental-library``.
.. [#note-P0355] P0355: The implementation status is:
* ``Calendars`` mostly done in Clang 7
Expand Down
2 changes: 1 addition & 1 deletion libcxx/docs/Status/Cxx20Papers.csv
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@
"`P0553R4 <https://wg21.link/P0553R4>`__","LWG","Bit operations","Cologne","|Complete|","9.0"
"`P0631R8 <https://wg21.link/P0631R8>`__","LWG","Math Constants","Cologne","|Complete|","11.0"
"`P0645R10 <https://wg21.link/P0645R10>`__","LWG","Text Formatting","Cologne","|Complete| [#note-P0645]_","14.0"
"`P0660R10 <https://wg21.link/P0660R10>`__","LWG","Stop Token and Joining Thread, Rev 10.","Cologne","|In Progress| [#note-P0660]_",""
"`P0660R10 <https://wg21.link/P0660R10>`__","LWG","Stop Token and Joining Thread, Rev 10.","Cologne","|Complete| [#note-P0660]_","18.0.0"
"`P0784R7 <https://wg21.link/P0784R7>`__","CWG","More constexpr containers","Cologne","|Complete|","12.0"
"`P0980R1 <https://wg21.link/P0980R1>`__","LWG","Making std::string constexpr","Cologne","|Complete|","15.0"
"`P1004R2 <https://wg21.link/P1004R2>`__","LWG","Making std::vector constexpr","Cologne","|Complete|","15.0"
Expand Down
4 changes: 2 additions & 2 deletions libcxx/include/__stop_token/stop_callback.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ _LIBCPP_PUSH_MACROS

_LIBCPP_BEGIN_NAMESPACE_STD

#if _LIBCPP_STD_VER >= 20 && !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_STOP_TOKEN)
#if _LIBCPP_STD_VER >= 20 && !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_STOP_TOKEN) && !defined(_LIBCPP_HAS_NO_THREADS)

template <class _Callback>
class _LIBCPP_AVAILABILITY_SYNC stop_callback : private __stop_callback_base {
Expand Down Expand Up @@ -101,4 +101,4 @@ _LIBCPP_END_NAMESPACE_STD

_LIBCPP_POP_MACROS

#endif // _LIBCPP_STD_VER >= 20 && !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_STOP_TOKEN)
#endif // _LIBCPP_STD_VER >= 20 && !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_STOP_TOKEN) && !defined(_LIBCPP_HAS_NO_THREADS)
4 changes: 2 additions & 2 deletions libcxx/include/__stop_token/stop_source.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@

_LIBCPP_BEGIN_NAMESPACE_STD

#if _LIBCPP_STD_VER >= 20 && !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_STOP_TOKEN)
#if _LIBCPP_STD_VER >= 20 && !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_STOP_TOKEN) && !defined(_LIBCPP_HAS_NO_THREADS)

struct nostopstate_t {
explicit nostopstate_t() = default;
Expand Down Expand Up @@ -89,4 +89,4 @@ class _LIBCPP_AVAILABILITY_SYNC stop_source {

_LIBCPP_END_NAMESPACE_STD

#endif // _LIBCPP_STD_VER >= 20 && !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_STOP_TOKEN)
#endif // _LIBCPP_STD_VER >= 20 && !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_STOP_TOKEN) && !defined(_LIBCPP_HAS_NO_THREADS)
4 changes: 2 additions & 2 deletions libcxx/include/__stop_token/stop_state.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@

_LIBCPP_BEGIN_NAMESPACE_STD

#if _LIBCPP_STD_VER >= 20
#if _LIBCPP_STD_VER >= 20 && !defined(_LIBCPP_HAS_NO_THREADS)

struct __stop_callback_base : __intrusive_node_base<__stop_callback_base> {
using __callback_fn_t = void(__stop_callback_base*) noexcept;
Expand Down Expand Up @@ -229,7 +229,7 @@ struct __intrusive_shared_ptr_traits<__stop_state> {
}
};

#endif // _LIBCPP_STD_VER >= 20
#endif // _LIBCPP_STD_VER >= 20 && !defined(_LIBCPP_HAS_NO_THREADS)

_LIBCPP_END_NAMESPACE_STD

Expand Down
4 changes: 2 additions & 2 deletions libcxx/include/__stop_token/stop_token.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@

_LIBCPP_BEGIN_NAMESPACE_STD

#if _LIBCPP_STD_VER >= 20 && !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_STOP_TOKEN)
#if _LIBCPP_STD_VER >= 20 && !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_STOP_TOKEN) && !defined(_LIBCPP_HAS_NO_THREADS)

class _LIBCPP_AVAILABILITY_SYNC stop_token {
public:
Expand Down Expand Up @@ -57,7 +57,7 @@ class _LIBCPP_AVAILABILITY_SYNC stop_token {
_LIBCPP_HIDE_FROM_ABI explicit stop_token(const __intrusive_shared_ptr<__stop_state>& __state) : __state_(__state) {}
};

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

_LIBCPP_END_NAMESPACE_STD

Expand Down
61 changes: 61 additions & 0 deletions libcxx/include/condition_variable
Original file line number Diff line number Diff line change
Expand Up @@ -100,13 +100,26 @@ public:
wait_for(Lock& lock,
const chrono::duration<Rep, Period>& rel_time,
Predicate pred);
// [thread.condvarany.intwait], interruptible waits
template <class Lock, class Predicate>
bool wait(Lock& lock, stop_token stoken, Predicate pred); // since C++20
template <class Lock, class Clock, class Duration, class Predicate>
bool wait_until(Lock& lock, stop_token stoken,
const chrono::time_point<Clock, Duration>& abs_time, Predicate pred); // since C++20
template <class Lock, class Rep, class Period, class Predicate>
bool wait_for(Lock& lock, stop_token stoken,
const chrono::duration<Rep, Period>& rel_time, Predicate pred); // since C++20
};
} // std
*/

#include <__assert> // all public C++ headers provide the assertion handler
#include <__availability>
#include <__chrono/duration.h>
#include <__chrono/steady_clock.h>
#include <__chrono/time_point.h>
Expand All @@ -118,6 +131,7 @@ public:
#include <__mutex/mutex.h>
#include <__mutex/tag_types.h>
#include <__mutex/unique_lock.h>
#include <__stop_token/stop_token.h>
#include <__utility/move.h>
#include <version>

Expand Down Expand Up @@ -174,6 +188,21 @@ public:
wait_for(_Lock& __lock,
const chrono::duration<_Rep, _Period>& __d,
_Predicate __pred);

#if _LIBCPP_STD_VER >= 20 && !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_STOP_TOKEN)

template <class _Lock, class _Predicate>
_LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI bool wait(_Lock& __lock, stop_token __stoken, _Predicate __pred);

template <class _Lock, class _Clock, class _Duration, class _Predicate>
_LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI bool wait_until(_Lock& __lock, stop_token __stoken,
const chrono::time_point<_Clock, _Duration>& __abs_time, _Predicate __pred);

template <class _Lock, class _Rep, class _Period, class _Predicate>
_LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI bool wait_for(_Lock& __lock, stop_token __stoken,
const chrono::duration<_Rep, _Period>& __rel_time, _Predicate __pred);

#endif // _LIBCPP_STD_VER >= 20 && !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_STOP_TOKEN)
};

inline
Expand Down Expand Up @@ -269,6 +298,38 @@ condition_variable_any::wait_for(_Lock& __lock,
_VSTD::move(__pred));
}

#if _LIBCPP_STD_VER >= 20 && !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_STOP_TOKEN)

template <class _Lock, class _Predicate>
bool condition_variable_any::wait(_Lock& __lock, stop_token __stoken, _Predicate __pred) {
while (!__stoken.stop_requested()) {
if (__pred())
return true;
wait(__lock);
}
return __pred();
}

template <class _Lock, class _Clock, class _Duration, class _Predicate>
bool condition_variable_any::wait_until(
_Lock& __lock, stop_token __stoken, const chrono::time_point<_Clock, _Duration>& __abs_time, _Predicate __pred) {
while (!__stoken.stop_requested()) {
if (__pred())
return true;
if (wait_until(__lock, __abs_time) == cv_status::timeout)
return __pred();
}
return __pred();
}

template <class _Lock, class _Rep, class _Period, class _Predicate>
bool condition_variable_any::wait_for(
_Lock& __lock, stop_token __stoken, const chrono::duration<_Rep, _Period>& __rel_time, _Predicate __pred) {
return wait_until(__lock, std::move(__stoken), chrono::steady_clock::now() + __rel_time, std::move(__pred));
}

#endif // _LIBCPP_STD_VER >= 20 && !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_STOP_TOKEN)

_LIBCPP_EXPORTED_FROM_ABI void notify_all_at_thread_exit(condition_variable&, unique_lock<mutex>);

_LIBCPP_END_NAMESPACE_STD
Expand Down
4 changes: 2 additions & 2 deletions libcxx/include/version
Original file line number Diff line number Diff line change
Expand Up @@ -372,8 +372,8 @@ __cpp_lib_within_lifetime 202306L <type_traits>
// # define __cpp_lib_is_layout_compatible 201907L
# define __cpp_lib_is_nothrow_convertible 201806L
// # define __cpp_lib_is_pointer_interconvertible 201907L
# if !defined(_LIBCPP_HAS_NO_THREADS)
// # define __cpp_lib_jthread 201911L
# if !defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_STOP_TOKEN) && !defined(_LIBCPP_AVAILABILITY_HAS_NO_SYNC)
# define __cpp_lib_jthread 201911L
# endif
# if !defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_AVAILABILITY_HAS_NO_SYNC)
# define __cpp_lib_latch 201907L
Expand Down
1 change: 1 addition & 0 deletions libcxx/test/libcxx/transitive_includes/cxx03.csv
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,7 @@ condition_variable cstdlib
condition_variable cstring
condition_variable ctime
condition_variable initializer_list
condition_variable iosfwd
condition_variable limits
condition_variable new
condition_variable ratio
Expand Down
1 change: 1 addition & 0 deletions libcxx/test/libcxx/transitive_includes/cxx11.csv
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,7 @@ condition_variable cstdlib
condition_variable cstring
condition_variable ctime
condition_variable initializer_list
condition_variable iosfwd
condition_variable limits
condition_variable new
condition_variable ratio
Expand Down
1 change: 1 addition & 0 deletions libcxx/test/libcxx/transitive_includes/cxx14.csv
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,7 @@ condition_variable cstdlib
condition_variable cstring
condition_variable ctime
condition_variable initializer_list
condition_variable iosfwd
condition_variable limits
condition_variable new
condition_variable ratio
Expand Down
1 change: 1 addition & 0 deletions libcxx/test/libcxx/transitive_includes/cxx17.csv
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,7 @@ condition_variable cstdlib
condition_variable cstring
condition_variable ctime
condition_variable initializer_list
condition_variable iosfwd
condition_variable limits
condition_variable new
condition_variable ratio
Expand Down
1 change: 1 addition & 0 deletions libcxx/test/libcxx/transitive_includes/cxx20.csv
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,7 @@ condition_variable cstdlib
condition_variable cstring
condition_variable ctime
condition_variable initializer_list
condition_variable iosfwd
condition_variable limits
condition_variable new
condition_variable ratio
Expand Down
3 changes: 3 additions & 0 deletions libcxx/test/libcxx/transitive_includes/cxx23.csv
Original file line number Diff line number Diff line change
Expand Up @@ -118,8 +118,11 @@ complex stdexcept
complex version
concepts cstddef
concepts version
condition_variable atomic
condition_variable cerrno
condition_variable cstddef
condition_variable cstdint
condition_variable cstring
condition_variable ctime
condition_variable iosfwd
condition_variable limits
Expand Down
3 changes: 3 additions & 0 deletions libcxx/test/libcxx/transitive_includes/cxx26.csv
Original file line number Diff line number Diff line change
Expand Up @@ -118,8 +118,11 @@ complex stdexcept
complex version
concepts cstddef
concepts version
condition_variable atomic
condition_variable cerrno
condition_variable cstddef
condition_variable cstdint
condition_variable cstring
condition_variable ctime
condition_variable iosfwd
condition_variable limits
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,46 +44,46 @@

#elif TEST_STD_VER == 20

# if !defined(_LIBCPP_VERSION)
# if !defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_STOP_TOKEN) && !defined(_LIBCPP_AVAILABILITY_HAS_NO_SYNC)
# ifndef __cpp_lib_jthread
# error "__cpp_lib_jthread should be defined in c++20"
# endif
# if __cpp_lib_jthread != 201911L
# error "__cpp_lib_jthread should have the value 201911L in c++20"
# endif
# else // _LIBCPP_VERSION
# else
# ifdef __cpp_lib_jthread
# error "__cpp_lib_jthread should not be defined because it is unimplemented in libc++!"
# error "__cpp_lib_jthread should not be defined when the requirement '!defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_STOP_TOKEN) && !defined(_LIBCPP_AVAILABILITY_HAS_NO_SYNC)' is not met!"
# endif
# endif

#elif TEST_STD_VER == 23

# if !defined(_LIBCPP_VERSION)
# if !defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_STOP_TOKEN) && !defined(_LIBCPP_AVAILABILITY_HAS_NO_SYNC)
# ifndef __cpp_lib_jthread
# error "__cpp_lib_jthread should be defined in c++23"
# endif
# if __cpp_lib_jthread != 201911L
# error "__cpp_lib_jthread should have the value 201911L in c++23"
# endif
# else // _LIBCPP_VERSION
# else
# ifdef __cpp_lib_jthread
# error "__cpp_lib_jthread should not be defined because it is unimplemented in libc++!"
# error "__cpp_lib_jthread should not be defined when the requirement '!defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_STOP_TOKEN) && !defined(_LIBCPP_AVAILABILITY_HAS_NO_SYNC)' is not met!"
# endif
# endif

#elif TEST_STD_VER > 23

# if !defined(_LIBCPP_VERSION)
# if !defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_STOP_TOKEN) && !defined(_LIBCPP_AVAILABILITY_HAS_NO_SYNC)
# ifndef __cpp_lib_jthread
# error "__cpp_lib_jthread should be defined in c++26"
# endif
# if __cpp_lib_jthread != 201911L
# error "__cpp_lib_jthread should have the value 201911L in c++26"
# endif
# else // _LIBCPP_VERSION
# else
# ifdef __cpp_lib_jthread
# error "__cpp_lib_jthread should not be defined because it is unimplemented in libc++!"
# error "__cpp_lib_jthread should not be defined when the requirement '!defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_STOP_TOKEN) && !defined(_LIBCPP_AVAILABILITY_HAS_NO_SYNC)' is not met!"
# endif
# endif

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,16 +61,16 @@
# error "__cpp_lib_formatters should not be defined before c++23"
# endif

# if !defined(_LIBCPP_VERSION)
# if !defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_STOP_TOKEN) && !defined(_LIBCPP_AVAILABILITY_HAS_NO_SYNC)
# ifndef __cpp_lib_jthread
# error "__cpp_lib_jthread should be defined in c++20"
# endif
# if __cpp_lib_jthread != 201911L
# error "__cpp_lib_jthread should have the value 201911L in c++20"
# endif
# else // _LIBCPP_VERSION
# else
# ifdef __cpp_lib_jthread
# error "__cpp_lib_jthread should not be defined because it is unimplemented in libc++!"
# error "__cpp_lib_jthread should not be defined when the requirement '!defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_STOP_TOKEN) && !defined(_LIBCPP_AVAILABILITY_HAS_NO_SYNC)' is not met!"
# endif
# endif

Expand All @@ -89,16 +89,16 @@
# endif
# endif

# if !defined(_LIBCPP_VERSION)
# if !defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_STOP_TOKEN) && !defined(_LIBCPP_AVAILABILITY_HAS_NO_SYNC)
# ifndef __cpp_lib_jthread
# error "__cpp_lib_jthread should be defined in c++23"
# endif
# if __cpp_lib_jthread != 201911L
# error "__cpp_lib_jthread should have the value 201911L in c++23"
# endif
# else // _LIBCPP_VERSION
# else
# ifdef __cpp_lib_jthread
# error "__cpp_lib_jthread should not be defined because it is unimplemented in libc++!"
# error "__cpp_lib_jthread should not be defined when the requirement '!defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_STOP_TOKEN) && !defined(_LIBCPP_AVAILABILITY_HAS_NO_SYNC)' is not met!"
# endif
# endif

Expand All @@ -117,16 +117,16 @@
# endif
# endif

# if !defined(_LIBCPP_VERSION)
# if !defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_STOP_TOKEN) && !defined(_LIBCPP_AVAILABILITY_HAS_NO_SYNC)
# ifndef __cpp_lib_jthread
# error "__cpp_lib_jthread should be defined in c++26"
# endif
# if __cpp_lib_jthread != 201911L
# error "__cpp_lib_jthread should have the value 201911L in c++26"
# endif
# else // _LIBCPP_VERSION
# else
# ifdef __cpp_lib_jthread
# error "__cpp_lib_jthread should not be defined because it is unimplemented in libc++!"
# error "__cpp_lib_jthread should not be defined when the requirement '!defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_STOP_TOKEN) && !defined(_LIBCPP_AVAILABILITY_HAS_NO_SYNC)' is not met!"
# endif
# endif

Expand Down
Loading

0 comments on commit 4fa812b

Please sign in to comment.