27
27
28
28
_LIBCPP_BEGIN_NAMESPACE_STD
29
29
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
+
30
58
template <class _Tp , bool = is_integral<_Tp>::value && !is_same<_Tp, bool >::value>
31
59
struct __atomic_base // false
32
60
{
@@ -44,6 +72,7 @@ struct __atomic_base // false
44
72
}
45
73
_LIBCPP_HIDE_FROM_ABI void store (_Tp __d, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT
46
74
_LIBCPP_CHECK_STORE_MEMORY_ORDER(__m) {
75
+ _LIBCPP_DEPRECATED_NOT_ALWAYS_LOCK_FREE (_Tp, is_always_lock_free);
47
76
std::__cxx_atomic_store (std::addressof (__a_), __d, __m);
48
77
}
49
78
_LIBCPP_HIDE_FROM_ABI void store (_Tp __d, memory_order __m = memory_order_seq_cst) _NOEXCEPT
@@ -52,15 +81,20 @@ struct __atomic_base // false
52
81
}
53
82
_LIBCPP_HIDE_FROM_ABI _Tp load (memory_order __m = memory_order_seq_cst) const volatile _NOEXCEPT
54
83
_LIBCPP_CHECK_LOAD_MEMORY_ORDER(__m) {
84
+ _LIBCPP_DEPRECATED_NOT_ALWAYS_LOCK_FREE (_Tp, is_always_lock_free);
55
85
return std::__cxx_atomic_load (std::addressof (__a_), __m);
56
86
}
57
87
_LIBCPP_HIDE_FROM_ABI _Tp load (memory_order __m = memory_order_seq_cst) const _NOEXCEPT
58
88
_LIBCPP_CHECK_LOAD_MEMORY_ORDER(__m) {
59
89
return std::__cxx_atomic_load (std::addressof (__a_), __m);
60
90
}
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
+ }
62
95
_LIBCPP_HIDE_FROM_ABI operator _Tp () const _NOEXCEPT { return load (); }
63
96
_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);
64
98
return std::__cxx_atomic_exchange (std::addressof (__a_), __d, __m);
65
99
}
66
100
_LIBCPP_HIDE_FROM_ABI _Tp exchange (_Tp __d, memory_order __m = memory_order_seq_cst) _NOEXCEPT {
@@ -69,6 +103,7 @@ struct __atomic_base // false
69
103
_LIBCPP_HIDE_FROM_ABI bool
70
104
compare_exchange_weak (_Tp& __e, _Tp __d, memory_order __s, memory_order __f) volatile _NOEXCEPT
71
105
_LIBCPP_CHECK_EXCHANGE_MEMORY_ORDER (__s, __f) {
106
+ _LIBCPP_DEPRECATED_NOT_ALWAYS_LOCK_FREE (_Tp, is_always_lock_free);
72
107
return std::__cxx_atomic_compare_exchange_weak (std::addressof (__a_), std::addressof (__e), __d, __s, __f);
73
108
}
74
109
_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
78
113
_LIBCPP_HIDE_FROM_ABI bool
79
114
compare_exchange_strong (_Tp& __e, _Tp __d, memory_order __s, memory_order __f) volatile _NOEXCEPT
80
115
_LIBCPP_CHECK_EXCHANGE_MEMORY_ORDER (__s, __f) {
116
+ _LIBCPP_DEPRECATED_NOT_ALWAYS_LOCK_FREE (_Tp, is_always_lock_free);
81
117
return std::__cxx_atomic_compare_exchange_strong (std::addressof (__a_), std::addressof (__e), __d, __s, __f);
82
118
}
83
119
_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
86
122
}
87
123
_LIBCPP_HIDE_FROM_ABI bool
88
124
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);
89
126
return std::__cxx_atomic_compare_exchange_weak (std::addressof (__a_), std::addressof (__e), __d, __m, __m);
90
127
}
91
128
_LIBCPP_HIDE_FROM_ABI bool
@@ -94,6 +131,7 @@ struct __atomic_base // false
94
131
}
95
132
_LIBCPP_HIDE_FROM_ABI bool
96
133
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);
97
135
return std::__cxx_atomic_compare_exchange_strong (std::addressof (__a_), std::addressof (__e), __d, __m, __m);
98
136
}
99
137
_LIBCPP_HIDE_FROM_ABI bool
@@ -142,54 +180,112 @@ struct __atomic_base<_Tp, true> : public __atomic_base<_Tp, false> {
142
180
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR __atomic_base (_Tp __d) _NOEXCEPT : __base(__d) {}
143
181
144
182
_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);
145
184
return std::__cxx_atomic_fetch_add (std::addressof (this ->__a_ ), __op, __m);
146
185
}
186
+
147
187
_LIBCPP_HIDE_FROM_ABI _Tp fetch_add (_Tp __op, memory_order __m = memory_order_seq_cst) _NOEXCEPT {
148
188
return std::__cxx_atomic_fetch_add (std::addressof (this ->__a_ ), __op, __m);
149
189
}
190
+
150
191
_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);
151
193
return std::__cxx_atomic_fetch_sub (std::addressof (this ->__a_ ), __op, __m);
152
194
}
195
+
153
196
_LIBCPP_HIDE_FROM_ABI _Tp fetch_sub (_Tp __op, memory_order __m = memory_order_seq_cst) _NOEXCEPT {
154
197
return std::__cxx_atomic_fetch_sub (std::addressof (this ->__a_ ), __op, __m);
155
198
}
199
+
156
200
_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);
157
202
return std::__cxx_atomic_fetch_and (std::addressof (this ->__a_ ), __op, __m);
158
203
}
204
+
159
205
_LIBCPP_HIDE_FROM_ABI _Tp fetch_and (_Tp __op, memory_order __m = memory_order_seq_cst) _NOEXCEPT {
160
206
return std::__cxx_atomic_fetch_and (std::addressof (this ->__a_ ), __op, __m);
161
207
}
208
+
162
209
_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);
163
211
return std::__cxx_atomic_fetch_or (std::addressof (this ->__a_ ), __op, __m);
164
212
}
213
+
165
214
_LIBCPP_HIDE_FROM_ABI _Tp fetch_or (_Tp __op, memory_order __m = memory_order_seq_cst) _NOEXCEPT {
166
215
return std::__cxx_atomic_fetch_or (std::addressof (this ->__a_ ), __op, __m);
167
216
}
217
+
168
218
_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);
169
220
return std::__cxx_atomic_fetch_xor (std::addressof (this ->__a_ ), __op, __m);
170
221
}
222
+
171
223
_LIBCPP_HIDE_FROM_ABI _Tp fetch_xor (_Tp __op, memory_order __m = memory_order_seq_cst) _NOEXCEPT {
172
224
return std::__cxx_atomic_fetch_xor (std::addressof (this ->__a_ ), __op, __m);
173
225
}
174
226
175
- _LIBCPP_HIDE_FROM_ABI _Tp operator ++(int ) volatile _NOEXCEPT { return fetch_add (_Tp (1 )); }
176
227
_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
+
178
234
_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
+
180
241
_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
+
182
248
_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
+
184
255
_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
+
186
262
_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
+
188
269
_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
+
190
276
_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
+
192
283
_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
+ }
193
289
};
194
290
195
291
// Here we need _IsIntegral because the default template argument is not enough
0 commit comments