2727
2828_LIBCPP_BEGIN_NAMESPACE_STD
2929
30+ #if _LIBCPP_STD_VER >= 20
31+ template <class _Tp , bool __lock_free>
32+ inline constexpr bool __deprecated_if_not_always_lock_free = true ;
33+
34+ template <class _Tp >
35+ [[deprecated(" volatile atomic operations are deprecated when std::atomic<T>::is_always_lock_free is false" )]]
36+ inline constexpr bool __deprecated_if_not_always_lock_free<_Tp, false > = true ;
37+
38+ // Many volatile overloads of of atomic<T> methods have a requirement to
39+ // guarantee atomic<T>::is_always_lock_free is truen in C++20.
40+ // To make this a non-breaking change, this macro is used to emit a warning
41+ // when atomic<T>::is_always_lock_free is false without having to duplicate
42+ // the method. We could do:
43+ //
44+ // _LIBCPP_HIDE_FROM_ABI void store(_Tp __d, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT
45+ // requires is_always_lock_free { ... }
46+ //
47+ // [[deprecated(...)]] _LIBCPP_HIDE_FROM_ABI void store(_Tp __d, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT
48+ // requires !is_always_lock_free { ... }
49+ //
50+ // But this creates a lot of unecessary duplicate code.
51+ # define _LIBCPP_DEPRECATED_NOT_ALWAYS_LOCK_FREE (_Tp, __is_always_lock_free ) \
52+ static_assert (__deprecated_if_not_always_lock_free<_Tp, __is_always_lock_free>)
53+ #else
54+ # define _LIBCPP_DEPRECATED_NOT_ALWAYS_LOCK_FREE (_Tp, __is_always_lock_free ) \
55+ {}
56+ #endif
57+
3058template <class _Tp , bool = is_integral<_Tp>::value && !is_same<_Tp, bool >::value>
3159struct __atomic_base // false
3260{
@@ -44,6 +72,7 @@ struct __atomic_base // false
4472 }
4573 _LIBCPP_HIDE_FROM_ABI void store (_Tp __d, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT
4674 _LIBCPP_CHECK_STORE_MEMORY_ORDER(__m) {
75+ _LIBCPP_DEPRECATED_NOT_ALWAYS_LOCK_FREE (_Tp, is_always_lock_free);
4776 std::__cxx_atomic_store (std::addressof (__a_), __d, __m);
4877 }
4978 _LIBCPP_HIDE_FROM_ABI void store (_Tp __d, memory_order __m = memory_order_seq_cst) _NOEXCEPT
@@ -52,15 +81,20 @@ struct __atomic_base // false
5281 }
5382 _LIBCPP_HIDE_FROM_ABI _Tp load (memory_order __m = memory_order_seq_cst) const volatile _NOEXCEPT
5483 _LIBCPP_CHECK_LOAD_MEMORY_ORDER(__m) {
84+ _LIBCPP_DEPRECATED_NOT_ALWAYS_LOCK_FREE (_Tp, is_always_lock_free);
5585 return std::__cxx_atomic_load (std::addressof (__a_), __m);
5686 }
5787 _LIBCPP_HIDE_FROM_ABI _Tp load (memory_order __m = memory_order_seq_cst) const _NOEXCEPT
5888 _LIBCPP_CHECK_LOAD_MEMORY_ORDER(__m) {
5989 return std::__cxx_atomic_load (std::addressof (__a_), __m);
6090 }
61- _LIBCPP_HIDE_FROM_ABI operator _Tp () const volatile _NOEXCEPT { return load (); }
91+ _LIBCPP_HIDE_FROM_ABI operator _Tp () const volatile _NOEXCEPT {
92+ _LIBCPP_DEPRECATED_NOT_ALWAYS_LOCK_FREE (_Tp, is_always_lock_free);
93+ return load ();
94+ }
6295 _LIBCPP_HIDE_FROM_ABI operator _Tp () const _NOEXCEPT { return load (); }
6396 _LIBCPP_HIDE_FROM_ABI _Tp exchange (_Tp __d, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT {
97+ _LIBCPP_DEPRECATED_NOT_ALWAYS_LOCK_FREE (_Tp, is_always_lock_free);
6498 return std::__cxx_atomic_exchange (std::addressof (__a_), __d, __m);
6599 }
66100 _LIBCPP_HIDE_FROM_ABI _Tp exchange (_Tp __d, memory_order __m = memory_order_seq_cst) _NOEXCEPT {
@@ -69,6 +103,7 @@ struct __atomic_base // false
69103 _LIBCPP_HIDE_FROM_ABI bool
70104 compare_exchange_weak (_Tp& __e, _Tp __d, memory_order __s, memory_order __f) volatile _NOEXCEPT
71105 _LIBCPP_CHECK_EXCHANGE_MEMORY_ORDER (__s, __f) {
106+ _LIBCPP_DEPRECATED_NOT_ALWAYS_LOCK_FREE (_Tp, is_always_lock_free);
72107 return std::__cxx_atomic_compare_exchange_weak (std::addressof (__a_), std::addressof (__e), __d, __s, __f);
73108 }
74109 _LIBCPP_HIDE_FROM_ABI bool compare_exchange_weak (_Tp& __e, _Tp __d, memory_order __s, memory_order __f) _NOEXCEPT
@@ -78,6 +113,7 @@ struct __atomic_base // false
78113 _LIBCPP_HIDE_FROM_ABI bool
79114 compare_exchange_strong (_Tp& __e, _Tp __d, memory_order __s, memory_order __f) volatile _NOEXCEPT
80115 _LIBCPP_CHECK_EXCHANGE_MEMORY_ORDER (__s, __f) {
116+ _LIBCPP_DEPRECATED_NOT_ALWAYS_LOCK_FREE (_Tp, is_always_lock_free);
81117 return std::__cxx_atomic_compare_exchange_strong (std::addressof (__a_), std::addressof (__e), __d, __s, __f);
82118 }
83119 _LIBCPP_HIDE_FROM_ABI bool compare_exchange_strong (_Tp& __e, _Tp __d, memory_order __s, memory_order __f) _NOEXCEPT
@@ -86,6 +122,7 @@ struct __atomic_base // false
86122 }
87123 _LIBCPP_HIDE_FROM_ABI bool
88124 compare_exchange_weak (_Tp& __e, _Tp __d, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT {
125+ _LIBCPP_DEPRECATED_NOT_ALWAYS_LOCK_FREE (_Tp, is_always_lock_free);
89126 return std::__cxx_atomic_compare_exchange_weak (std::addressof (__a_), std::addressof (__e), __d, __m, __m);
90127 }
91128 _LIBCPP_HIDE_FROM_ABI bool
@@ -94,6 +131,7 @@ struct __atomic_base // false
94131 }
95132 _LIBCPP_HIDE_FROM_ABI bool
96133 compare_exchange_strong (_Tp& __e, _Tp __d, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT {
134+ _LIBCPP_DEPRECATED_NOT_ALWAYS_LOCK_FREE (_Tp, is_always_lock_free);
97135 return std::__cxx_atomic_compare_exchange_strong (std::addressof (__a_), std::addressof (__e), __d, __m, __m);
98136 }
99137 _LIBCPP_HIDE_FROM_ABI bool
@@ -142,54 +180,112 @@ struct __atomic_base<_Tp, true> : public __atomic_base<_Tp, false> {
142180 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR __atomic_base (_Tp __d) _NOEXCEPT : __base(__d) {}
143181
144182 _LIBCPP_HIDE_FROM_ABI _Tp fetch_add (_Tp __op, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT {
183+ _LIBCPP_DEPRECATED_NOT_ALWAYS_LOCK_FREE (_Tp, __base::is_always_lock_free);
145184 return std::__cxx_atomic_fetch_add (std::addressof (this ->__a_ ), __op, __m);
146185 }
186+
147187 _LIBCPP_HIDE_FROM_ABI _Tp fetch_add (_Tp __op, memory_order __m = memory_order_seq_cst) _NOEXCEPT {
148188 return std::__cxx_atomic_fetch_add (std::addressof (this ->__a_ ), __op, __m);
149189 }
190+
150191 _LIBCPP_HIDE_FROM_ABI _Tp fetch_sub (_Tp __op, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT {
192+ _LIBCPP_DEPRECATED_NOT_ALWAYS_LOCK_FREE (_Tp, __base::is_always_lock_free);
151193 return std::__cxx_atomic_fetch_sub (std::addressof (this ->__a_ ), __op, __m);
152194 }
195+
153196 _LIBCPP_HIDE_FROM_ABI _Tp fetch_sub (_Tp __op, memory_order __m = memory_order_seq_cst) _NOEXCEPT {
154197 return std::__cxx_atomic_fetch_sub (std::addressof (this ->__a_ ), __op, __m);
155198 }
199+
156200 _LIBCPP_HIDE_FROM_ABI _Tp fetch_and (_Tp __op, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT {
201+ _LIBCPP_DEPRECATED_NOT_ALWAYS_LOCK_FREE (_Tp, __base::is_always_lock_free);
157202 return std::__cxx_atomic_fetch_and (std::addressof (this ->__a_ ), __op, __m);
158203 }
204+
159205 _LIBCPP_HIDE_FROM_ABI _Tp fetch_and (_Tp __op, memory_order __m = memory_order_seq_cst) _NOEXCEPT {
160206 return std::__cxx_atomic_fetch_and (std::addressof (this ->__a_ ), __op, __m);
161207 }
208+
162209 _LIBCPP_HIDE_FROM_ABI _Tp fetch_or (_Tp __op, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT {
210+ _LIBCPP_DEPRECATED_NOT_ALWAYS_LOCK_FREE (_Tp, __base::is_always_lock_free);
163211 return std::__cxx_atomic_fetch_or (std::addressof (this ->__a_ ), __op, __m);
164212 }
213+
165214 _LIBCPP_HIDE_FROM_ABI _Tp fetch_or (_Tp __op, memory_order __m = memory_order_seq_cst) _NOEXCEPT {
166215 return std::__cxx_atomic_fetch_or (std::addressof (this ->__a_ ), __op, __m);
167216 }
217+
168218 _LIBCPP_HIDE_FROM_ABI _Tp fetch_xor (_Tp __op, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT {
219+ _LIBCPP_DEPRECATED_NOT_ALWAYS_LOCK_FREE (_Tp, __base::is_always_lock_free);
169220 return std::__cxx_atomic_fetch_xor (std::addressof (this ->__a_ ), __op, __m);
170221 }
222+
171223 _LIBCPP_HIDE_FROM_ABI _Tp fetch_xor (_Tp __op, memory_order __m = memory_order_seq_cst) _NOEXCEPT {
172224 return std::__cxx_atomic_fetch_xor (std::addressof (this ->__a_ ), __op, __m);
173225 }
174226
175- _LIBCPP_HIDE_FROM_ABI _Tp operator ++(int ) volatile _NOEXCEPT { return fetch_add (_Tp (1 )); }
176227 _LIBCPP_HIDE_FROM_ABI _Tp operator ++(int ) _NOEXCEPT { return fetch_add (_Tp (1 )); }
177- _LIBCPP_HIDE_FROM_ABI _Tp operator --(int ) volatile _NOEXCEPT { return fetch_sub (_Tp (1 )); }
228+
229+ _LIBCPP_HIDE_FROM_ABI _Tp operator ++(int ) volatile _NOEXCEPT {
230+ _LIBCPP_DEPRECATED_NOT_ALWAYS_LOCK_FREE (_Tp, __base::is_always_lock_free);
231+ return fetch_add (_Tp (1 ));
232+ }
233+
178234 _LIBCPP_HIDE_FROM_ABI _Tp operator --(int ) _NOEXCEPT { return fetch_sub (_Tp (1 )); }
179- _LIBCPP_HIDE_FROM_ABI _Tp operator ++() volatile _NOEXCEPT { return fetch_add (_Tp (1 )) + _Tp (1 ); }
235+
236+ _LIBCPP_HIDE_FROM_ABI _Tp operator --(int ) volatile _NOEXCEPT {
237+ _LIBCPP_DEPRECATED_NOT_ALWAYS_LOCK_FREE (_Tp, __base::is_always_lock_free);
238+ return fetch_sub (_Tp (1 ));
239+ }
240+
180241 _LIBCPP_HIDE_FROM_ABI _Tp operator ++() _NOEXCEPT { return fetch_add (_Tp (1 )) + _Tp (1 ); }
181- _LIBCPP_HIDE_FROM_ABI _Tp operator --() volatile _NOEXCEPT { return fetch_sub (_Tp (1 )) - _Tp (1 ); }
242+
243+ _LIBCPP_HIDE_FROM_ABI _Tp operator ++() volatile _NOEXCEPT {
244+ _LIBCPP_DEPRECATED_NOT_ALWAYS_LOCK_FREE (_Tp, __base::is_always_lock_free);
245+ return fetch_add (_Tp (1 )) + _Tp (1 );
246+ }
247+
182248 _LIBCPP_HIDE_FROM_ABI _Tp operator --() _NOEXCEPT { return fetch_sub (_Tp (1 )) - _Tp (1 ); }
183- _LIBCPP_HIDE_FROM_ABI _Tp operator +=(_Tp __op) volatile _NOEXCEPT { return fetch_add (__op) + __op; }
249+
250+ _LIBCPP_HIDE_FROM_ABI _Tp operator --() volatile _NOEXCEPT {
251+ _LIBCPP_DEPRECATED_NOT_ALWAYS_LOCK_FREE (_Tp, __base::is_always_lock_free);
252+ return fetch_sub (_Tp (1 )) - _Tp (1 );
253+ }
254+
184255 _LIBCPP_HIDE_FROM_ABI _Tp operator +=(_Tp __op) _NOEXCEPT { return fetch_add (__op) + __op; }
185- _LIBCPP_HIDE_FROM_ABI _Tp operator -=(_Tp __op) volatile _NOEXCEPT { return fetch_sub (__op) - __op; }
256+
257+ _LIBCPP_HIDE_FROM_ABI _Tp operator +=(_Tp __op) volatile _NOEXCEPT {
258+ _LIBCPP_DEPRECATED_NOT_ALWAYS_LOCK_FREE (_Tp, __base::is_always_lock_free);
259+ return fetch_add (__op) + __op;
260+ }
261+
186262 _LIBCPP_HIDE_FROM_ABI _Tp operator -=(_Tp __op) _NOEXCEPT { return fetch_sub (__op) - __op; }
187- _LIBCPP_HIDE_FROM_ABI _Tp operator &=(_Tp __op) volatile _NOEXCEPT { return fetch_and (__op) & __op; }
263+
264+ _LIBCPP_HIDE_FROM_ABI _Tp operator -=(_Tp __op) volatile _NOEXCEPT {
265+ _LIBCPP_DEPRECATED_NOT_ALWAYS_LOCK_FREE (_Tp, __base::is_always_lock_free);
266+ return fetch_sub (__op) - __op;
267+ }
268+
188269 _LIBCPP_HIDE_FROM_ABI _Tp operator &=(_Tp __op) _NOEXCEPT { return fetch_and (__op) & __op; }
189- _LIBCPP_HIDE_FROM_ABI _Tp operator |=(_Tp __op) volatile _NOEXCEPT { return fetch_or (__op) | __op; }
270+
271+ _LIBCPP_HIDE_FROM_ABI _Tp operator &=(_Tp __op) volatile _NOEXCEPT {
272+ _LIBCPP_DEPRECATED_NOT_ALWAYS_LOCK_FREE (_Tp, __base::is_always_lock_free);
273+ return fetch_and (__op) & __op;
274+ }
275+
190276 _LIBCPP_HIDE_FROM_ABI _Tp operator |=(_Tp __op) _NOEXCEPT { return fetch_or (__op) | __op; }
191- _LIBCPP_HIDE_FROM_ABI _Tp operator ^=(_Tp __op) volatile _NOEXCEPT { return fetch_xor (__op) ^ __op; }
277+
278+ _LIBCPP_HIDE_FROM_ABI _Tp operator |=(_Tp __op) volatile _NOEXCEPT {
279+ _LIBCPP_DEPRECATED_NOT_ALWAYS_LOCK_FREE (_Tp, __base::is_always_lock_free);
280+ return fetch_or (__op) | __op;
281+ }
282+
192283 _LIBCPP_HIDE_FROM_ABI _Tp operator ^=(_Tp __op) _NOEXCEPT { return fetch_xor (__op) ^ __op; }
284+
285+ _LIBCPP_HIDE_FROM_ABI _Tp operator ^=(_Tp __op) volatile _NOEXCEPT {
286+ _LIBCPP_DEPRECATED_NOT_ALWAYS_LOCK_FREE (_Tp, __base::is_always_lock_free);
287+ return fetch_xor (__op) ^ __op;
288+ }
193289};
194290
195291// Here we need _IsIntegral because the default template argument is not enough
0 commit comments