21
21
#include < __type_traits/conjunction.h>
22
22
#include < __type_traits/decay.h>
23
23
#include < __type_traits/invoke.h>
24
+ #include < __type_traits/void_t.h>
24
25
#include < __utility/declval.h>
25
26
#include < cstring>
26
27
@@ -36,40 +37,30 @@ _LIBCPP_BEGIN_NAMESPACE_STD
36
37
// - __atomic_notify_one
37
38
// - __atomic_notify_all
38
39
// Note that std::atomic<T>::wait was back-ported to C++03
39
- // there the below implementations look ugly to support C++03
40
-
41
- // NOLINTBEGIN(libcpp-robust-against-adl)
42
- struct __atomic_load_cpo {
43
- template <class _Tp >
44
- using _Ret = decltype (__tag_invoke(
45
- std::declval<__atomic_load_cpo>(), std::declval<const _Tp&>(), std::declval<memory_order>()));
46
-
47
- template <class _Tp >
48
- _LIBCPP_HIDE_FROM_ABI _Ret<_Tp> operator ()(const _Tp& __t , memory_order __order) const _NOEXCEPT {
49
- return __tag_invoke (*this , __t , __order);
50
- }
40
+ // The below implementations look ugly to support C++03
41
+ template <class _Tp , class = void >
42
+ struct __atomic_waitable_customisations {
43
+ template <class _AtomicWaitable >
44
+ static void __atomic_load (_AtomicWaitable&&, memory_order) = delete;
45
+
46
+ template <class _AtomicWaitable >
47
+ static void __atomic_contention_address (_AtomicWaitable&&) = delete;
51
48
};
52
- // TODO: if we can deprecate std::atomic<T>::wait before c++17, we could add
53
- // inline constexpr __atomic_load_cpo __atomic_load{};
54
-
55
- struct __atomic_contention_address_cpo {
56
- template <class _Tp >
57
- using _Ret = decltype (__tag_invoke(std::declval<__atomic_contention_address_cpo>(), std::declval<const _Tp&>()));
58
49
59
- template <class _Tp >
60
- _LIBCPP_HIDE_FROM_ABI _Ret<_Tp> operator ()(const _Tp& __t ) const _NOEXCEPT {
61
- return __tag_invoke (*this , __t );
62
- }
63
- };
64
- // TODO: if we can deprecate std::atomic<T>::wait before c++17, we could add
65
- // inline constexpr __atomic_contention_address_cpo __atomic_contention_address{};
50
+ template <class _Tp >
51
+ struct __atomic_waitable_customisations <_Tp, __enable_if_t <!__is_same(_Tp, __decay_t <_Tp>)> >
52
+ : __atomic_waitable_customisations<__decay_t <_Tp> > {};
66
53
67
- // NOLINTEND(libcpp-robust-against-adl)
54
+ template <class _Tp , class = void >
55
+ struct __atomic_waitable : false_type {};
68
56
69
57
template <class _Tp >
70
- using __atomic_waitable =
71
- _And<__invokable<__atomic_load_cpo, const _Tp&, memory_order>,
72
- __invokable<__atomic_contention_address_cpo, const _Tp&> >;
58
+ struct __atomic_waitable <
59
+ _Tp,
60
+ __void_t <decltype (__atomic_waitable_customisations<_Tp>::__atomic_load(
61
+ std::declval<const _Tp&>(), std::declval<memory_order>())),
62
+ decltype (__atomic_waitable_customisations<_Tp>::__atomic_contention_address(std::declval<const _Tp&>()))> >
63
+ : true_type {};
73
64
74
65
template <class _AtomicWaitable , class _Poll >
75
66
struct __atomic_wait_poll_impl {
@@ -78,8 +69,7 @@ struct __atomic_wait_poll_impl {
78
69
memory_order __order_;
79
70
80
71
_LIBCPP_HIDE_FROM_ABI bool operator ()() const {
81
- __atomic_load_cpo __atomic_load = {};
82
- auto __current_val = __atomic_load (__a_, __order_);
72
+ auto __current_val = __atomic_waitable_customisations<_AtomicWaitable>::__atomic_load (__a_, __order_);
83
73
return __poll_ (__current_val);
84
74
}
85
75
};
@@ -111,8 +101,7 @@ struct __atomic_wait_backoff_impl {
111
101
__update_monitor_val_and_poll (__cxx_atomic_contention_t const volatile *, __cxx_contention_t & __monitor_val) const {
112
102
// In case the contention type happens to be __cxx_atomic_contention_t, i.e. __cxx_atomic_impl<int64_t>,
113
103
// the platform wait is directly monitoring the atomic value itself.
114
- __atomic_load_cpo __atomic_load = {};
115
- __monitor_val = __atomic_load (__a_, __order_);
104
+ __monitor_val = __atomic_waitable_customisations<_AtomicWaitable>::__atomic_load (__a_, __order_);
116
105
return __poll_ (__monitor_val);
117
106
}
118
107
@@ -121,17 +110,15 @@ struct __atomic_wait_backoff_impl {
121
110
__update_monitor_val_and_poll (void const volatile * __contention_address, __cxx_contention_t & __monitor_val) const {
122
111
// In case the contention type is anything else, platform wait is monitoring a __cxx_atomic_contention_t
123
112
// from the global pool, the monitor comes from __libcpp_atomic_monitor
124
- __monitor_val = std::__libcpp_atomic_monitor (__contention_address);
125
- __atomic_load_cpo __atomic_load = {};
126
- auto __current_val = __atomic_load (__a_, __order_);
113
+ __monitor_val = std::__libcpp_atomic_monitor (__contention_address);
114
+ auto __current_val = __atomic_waitable_customisations<_AtomicWaitable>::__atomic_load (__a_, __order_);
127
115
return __poll_ (__current_val);
128
116
}
129
117
130
118
_LIBCPP_AVAILABILITY_SYNC
131
119
_LIBCPP_HIDE_FROM_ABI bool operator ()(chrono::nanoseconds __elapsed) const {
132
120
if (__elapsed > chrono::microseconds (64 )) {
133
- __atomic_contention_address_cpo __atomic_contention_address = {};
134
- auto __contention_address = __atomic_contention_address (__a_);
121
+ auto __contention_address = __atomic_waitable_customisations<_AtomicWaitable>::__atomic_contention_address (__a_);
135
122
__cxx_contention_t __monitor_val;
136
123
if (__update_monitor_val_and_poll (__contention_address, __monitor_val))
137
124
return true ;
@@ -156,15 +143,13 @@ __atomic_wait_unless(const _AtomicWaitable& __a, _Poll&& __poll, memory_order __
156
143
template <class _AtomicWaitable >
157
144
_LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void __atomic_notify_one (const _AtomicWaitable& __a) {
158
145
static_assert (__atomic_waitable<_AtomicWaitable>::value, " " );
159
- __atomic_contention_address_cpo __atomic_contention_address = {};
160
- std::__cxx_atomic_notify_one (__atomic_contention_address (__a));
146
+ std::__cxx_atomic_notify_one (__atomic_waitable_customisations<_AtomicWaitable>::__atomic_contention_address (__a));
161
147
}
162
148
163
149
template <class _AtomicWaitable >
164
150
_LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void __atomic_notify_all (const _AtomicWaitable& __a) {
165
151
static_assert (__atomic_waitable<_AtomicWaitable>::value, " " );
166
- __atomic_contention_address_cpo __atomic_contention_address = {};
167
- std::__cxx_atomic_notify_all (__atomic_contention_address (__a));
152
+ std::__cxx_atomic_notify_all (__atomic_waitable_customisations<_AtomicWaitable>::__atomic_contention_address (__a));
168
153
}
169
154
170
155
#else // _LIBCPP_HAS_NO_THREADS
@@ -199,6 +184,7 @@ struct __bind_nonatomic_equal {
199
184
template <class _AtomicWaitable , class _Up >
200
185
_LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void
201
186
__atomic_wait (_AtomicWaitable& __a, _Up __val, memory_order __order) {
187
+ static_assert (__atomic_waitable<_AtomicWaitable>::value, " " );
202
188
__bind_nonatomic_equal<_Up> __nonatomic_equal = {__val};
203
189
std::__atomic_wait_unless (__a, __nonatomic_equal, __order);
204
190
}
0 commit comments