1// -*- C++ -*-
2//===----------------------------------------------------------------------===//
3//
4// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5// See https://llvm.org/LICENSE.txt for license information.
6// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7//
8//===----------------------------------------------------------------------===//
9
10#ifndef _LIBCPP_ATOMIC
11#define _LIBCPP_ATOMIC
12
13/*
14 atomic synopsis
15
16namespace std
17{
18
19// feature test macro [version.syn]
20
21#define __cpp_lib_atomic_is_always_lock_free
22#define __cpp_lib_atomic_flag_test
23#define __cpp_lib_atomic_lock_free_type_aliases
24#define __cpp_lib_atomic_wait
25
26 // order and consistency
27
28 enum memory_order: unspecified // enum class in C++20
29 {
30 relaxed,
31 consume, // load-consume
32 acquire, // load-acquire
33 release, // store-release
34 acq_rel, // store-release load-acquire
35 seq_cst // store-release load-acquire
36 };
37
38 inline constexpr auto memory_order_relaxed = memory_order::relaxed;
39 inline constexpr auto memory_order_consume = memory_order::consume;
40 inline constexpr auto memory_order_acquire = memory_order::acquire;
41 inline constexpr auto memory_order_release = memory_order::release;
42 inline constexpr auto memory_order_acq_rel = memory_order::acq_rel;
43 inline constexpr auto memory_order_seq_cst = memory_order::seq_cst;
44
45template <class T> T kill_dependency(T y) noexcept;
46
47// lock-free property
48
49#define ATOMIC_BOOL_LOCK_FREE unspecified
50#define ATOMIC_CHAR_LOCK_FREE unspecified
51#define ATOMIC_CHAR8_T_LOCK_FREE unspecified // C++20
52#define ATOMIC_CHAR16_T_LOCK_FREE unspecified
53#define ATOMIC_CHAR32_T_LOCK_FREE unspecified
54#define ATOMIC_WCHAR_T_LOCK_FREE unspecified
55#define ATOMIC_SHORT_LOCK_FREE unspecified
56#define ATOMIC_INT_LOCK_FREE unspecified
57#define ATOMIC_LONG_LOCK_FREE unspecified
58#define ATOMIC_LLONG_LOCK_FREE unspecified
59#define ATOMIC_POINTER_LOCK_FREE unspecified
60
61template <class T>
62struct atomic
63{
64 using value_type = T;
65
66 static constexpr bool is_always_lock_free;
67 bool is_lock_free() const volatile noexcept;
68 bool is_lock_free() const noexcept;
69
70 atomic() noexcept = default; // until C++20
71 constexpr atomic() noexcept(is_nothrow_default_constructible_v<T>); // since C++20
72 constexpr atomic(T desr) noexcept;
73 atomic(const atomic&) = delete;
74 atomic& operator=(const atomic&) = delete;
75 atomic& operator=(const atomic&) volatile = delete;
76
77 T load(memory_order m = memory_order_seq_cst) const volatile noexcept;
78 T load(memory_order m = memory_order_seq_cst) const noexcept;
79 operator T() const volatile noexcept;
80 operator T() const noexcept;
81 void store(T desr, memory_order m = memory_order_seq_cst) volatile noexcept;
82 void store(T desr, memory_order m = memory_order_seq_cst) noexcept;
83 T operator=(T) volatile noexcept;
84 T operator=(T) noexcept;
85
86 T exchange(T desr, memory_order m = memory_order_seq_cst) volatile noexcept;
87 T exchange(T desr, memory_order m = memory_order_seq_cst) noexcept;
88 bool compare_exchange_weak(T& expc, T desr,
89 memory_order s, memory_order f) volatile noexcept;
90 bool compare_exchange_weak(T& expc, T desr, memory_order s, memory_order f) noexcept;
91 bool compare_exchange_strong(T& expc, T desr,
92 memory_order s, memory_order f) volatile noexcept;
93 bool compare_exchange_strong(T& expc, T desr,
94 memory_order s, memory_order f) noexcept;
95 bool compare_exchange_weak(T& expc, T desr,
96 memory_order m = memory_order_seq_cst) volatile noexcept;
97 bool compare_exchange_weak(T& expc, T desr,
98 memory_order m = memory_order_seq_cst) noexcept;
99 bool compare_exchange_strong(T& expc, T desr,
100 memory_order m = memory_order_seq_cst) volatile noexcept;
101 bool compare_exchange_strong(T& expc, T desr,
102 memory_order m = memory_order_seq_cst) noexcept;
103
104 void wait(T, memory_order = memory_order::seq_cst) const volatile noexcept;
105 void wait(T, memory_order = memory_order::seq_cst) const noexcept;
106 void notify_one() volatile noexcept;
107 void notify_one() noexcept;
108 void notify_all() volatile noexcept;
109 void notify_all() noexcept;
110};
111
112template <>
113struct atomic<integral>
114{
115 using value_type = integral;
116 using difference_type = value_type;
117
118 static constexpr bool is_always_lock_free;
119 bool is_lock_free() const volatile noexcept;
120 bool is_lock_free() const noexcept;
121
122 atomic() noexcept = default;
123 constexpr atomic(integral desr) noexcept;
124 atomic(const atomic&) = delete;
125 atomic& operator=(const atomic&) = delete;
126 atomic& operator=(const atomic&) volatile = delete;
127
128 integral load(memory_order m = memory_order_seq_cst) const volatile noexcept;
129 integral load(memory_order m = memory_order_seq_cst) const noexcept;
130 operator integral() const volatile noexcept;
131 operator integral() const noexcept;
132 void store(integral desr, memory_order m = memory_order_seq_cst) volatile noexcept;
133 void store(integral desr, memory_order m = memory_order_seq_cst) noexcept;
134 integral operator=(integral desr) volatile noexcept;
135 integral operator=(integral desr) noexcept;
136
137 integral exchange(integral desr,
138 memory_order m = memory_order_seq_cst) volatile noexcept;
139 integral exchange(integral desr, memory_order m = memory_order_seq_cst) noexcept;
140 bool compare_exchange_weak(integral& expc, integral desr,
141 memory_order s, memory_order f) volatile noexcept;
142 bool compare_exchange_weak(integral& expc, integral desr,
143 memory_order s, memory_order f) noexcept;
144 bool compare_exchange_strong(integral& expc, integral desr,
145 memory_order s, memory_order f) volatile noexcept;
146 bool compare_exchange_strong(integral& expc, integral desr,
147 memory_order s, memory_order f) noexcept;
148 bool compare_exchange_weak(integral& expc, integral desr,
149 memory_order m = memory_order_seq_cst) volatile noexcept;
150 bool compare_exchange_weak(integral& expc, integral desr,
151 memory_order m = memory_order_seq_cst) noexcept;
152 bool compare_exchange_strong(integral& expc, integral desr,
153 memory_order m = memory_order_seq_cst) volatile noexcept;
154 bool compare_exchange_strong(integral& expc, integral desr,
155 memory_order m = memory_order_seq_cst) noexcept;
156
157 integral fetch_add(integral op, memory_order m = memory_order_seq_cst) volatile noexcept;
158 integral fetch_add(integral op, memory_order m = memory_order_seq_cst) noexcept;
159 integral fetch_sub(integral op, memory_order m = memory_order_seq_cst) volatile noexcept;
160 integral fetch_sub(integral op, memory_order m = memory_order_seq_cst) noexcept;
161 integral fetch_and(integral op, memory_order m = memory_order_seq_cst) volatile noexcept;
162 integral fetch_and(integral op, memory_order m = memory_order_seq_cst) noexcept;
163 integral fetch_or(integral op, memory_order m = memory_order_seq_cst) volatile noexcept;
164 integral fetch_or(integral op, memory_order m = memory_order_seq_cst) noexcept;
165 integral fetch_xor(integral op, memory_order m = memory_order_seq_cst) volatile noexcept;
166 integral fetch_xor(integral op, memory_order m = memory_order_seq_cst) noexcept;
167
168 integral operator++(int) volatile noexcept;
169 integral operator++(int) noexcept;
170 integral operator--(int) volatile noexcept;
171 integral operator--(int) noexcept;
172 integral operator++() volatile noexcept;
173 integral operator++() noexcept;
174 integral operator--() volatile noexcept;
175 integral operator--() noexcept;
176 integral operator+=(integral op) volatile noexcept;
177 integral operator+=(integral op) noexcept;
178 integral operator-=(integral op) volatile noexcept;
179 integral operator-=(integral op) noexcept;
180 integral operator&=(integral op) volatile noexcept;
181 integral operator&=(integral op) noexcept;
182 integral operator|=(integral op) volatile noexcept;
183 integral operator|=(integral op) noexcept;
184 integral operator^=(integral op) volatile noexcept;
185 integral operator^=(integral op) noexcept;
186
187 void wait(integral, memory_order = memory_order::seq_cst) const volatile noexcept;
188 void wait(integral, memory_order = memory_order::seq_cst) const noexcept;
189 void notify_one() volatile noexcept;
190 void notify_one() noexcept;
191 void notify_all() volatile noexcept;
192 void notify_all() noexcept;
193};
194
195template <class T>
196struct atomic<T*>
197{
198 using value_type = T*;
199 using difference_type = ptrdiff_t;
200
201 static constexpr bool is_always_lock_free;
202 bool is_lock_free() const volatile noexcept;
203 bool is_lock_free() const noexcept;
204
205 atomic() noexcept = default; // until C++20
206 constexpr atomic() noexcept; // since C++20
207 constexpr atomic(T* desr) noexcept;
208 atomic(const atomic&) = delete;
209 atomic& operator=(const atomic&) = delete;
210 atomic& operator=(const atomic&) volatile = delete;
211
212 T* load(memory_order m = memory_order_seq_cst) const volatile noexcept;
213 T* load(memory_order m = memory_order_seq_cst) const noexcept;
214 operator T*() const volatile noexcept;
215 operator T*() const noexcept;
216 void store(T* desr, memory_order m = memory_order_seq_cst) volatile noexcept;
217 void store(T* desr, memory_order m = memory_order_seq_cst) noexcept;
218 T* operator=(T*) volatile noexcept;
219 T* operator=(T*) noexcept;
220
221 T* exchange(T* desr, memory_order m = memory_order_seq_cst) volatile noexcept;
222 T* exchange(T* desr, memory_order m = memory_order_seq_cst) noexcept;
223 bool compare_exchange_weak(T*& expc, T* desr,
224 memory_order s, memory_order f) volatile noexcept;
225 bool compare_exchange_weak(T*& expc, T* desr,
226 memory_order s, memory_order f) noexcept;
227 bool compare_exchange_strong(T*& expc, T* desr,
228 memory_order s, memory_order f) volatile noexcept;
229 bool compare_exchange_strong(T*& expc, T* desr,
230 memory_order s, memory_order f) noexcept;
231 bool compare_exchange_weak(T*& expc, T* desr,
232 memory_order m = memory_order_seq_cst) volatile noexcept;
233 bool compare_exchange_weak(T*& expc, T* desr,
234 memory_order m = memory_order_seq_cst) noexcept;
235 bool compare_exchange_strong(T*& expc, T* desr,
236 memory_order m = memory_order_seq_cst) volatile noexcept;
237 bool compare_exchange_strong(T*& expc, T* desr,
238 memory_order m = memory_order_seq_cst) noexcept;
239 T* fetch_add(ptrdiff_t op, memory_order m = memory_order_seq_cst) volatile noexcept;
240 T* fetch_add(ptrdiff_t op, memory_order m = memory_order_seq_cst) noexcept;
241 T* fetch_sub(ptrdiff_t op, memory_order m = memory_order_seq_cst) volatile noexcept;
242 T* fetch_sub(ptrdiff_t op, memory_order m = memory_order_seq_cst) noexcept;
243
244 T* operator++(int) volatile noexcept;
245 T* operator++(int) noexcept;
246 T* operator--(int) volatile noexcept;
247 T* operator--(int) noexcept;
248 T* operator++() volatile noexcept;
249 T* operator++() noexcept;
250 T* operator--() volatile noexcept;
251 T* operator--() noexcept;
252 T* operator+=(ptrdiff_t op) volatile noexcept;
253 T* operator+=(ptrdiff_t op) noexcept;
254 T* operator-=(ptrdiff_t op) volatile noexcept;
255 T* operator-=(ptrdiff_t op) noexcept;
256
257 void wait(T*, memory_order = memory_order::seq_cst) const volatile noexcept;
258 void wait(T*, memory_order = memory_order::seq_cst) const noexcept;
259 void notify_one() volatile noexcept;
260 void notify_one() noexcept;
261 void notify_all() volatile noexcept;
262 void notify_all() noexcept;
263};
264
265template<>
266struct atomic<floating-point-type> { // since C++20
267 using value_type = floating-point-type;
268 using difference_type = value_type;
269
270 static constexpr bool is_always_lock_free = implementation-defined;
271 bool is_lock_free() const volatile noexcept;
272 bool is_lock_free() const noexcept;
273
274 constexpr atomic() noexcept;
275 constexpr atomic(floating-point-type) noexcept;
276 atomic(const atomic&) = delete;
277 atomic& operator=(const atomic&) = delete;
278 atomic& operator=(const atomic&) volatile = delete;
279
280 void store(floating-point-type, memory_order = memory_order::seq_cst) volatile noexcept;
281 void store(floating-point-type, memory_order = memory_order::seq_cst) noexcept;
282 floating-point-type operator=(floating-point-type) volatile noexcept;
283 floating-point-type operator=(floating-point-type) noexcept;
284 floating-point-type load(memory_order = memory_order::seq_cst) volatile noexcept;
285 floating-point-type load(memory_order = memory_order::seq_cst) noexcept;
286 operator floating-point-type() volatile noexcept;
287 operator floating-point-type() noexcept;
288
289 floating-point-type exchange(floating-point-type,
290 memory_order = memory_order::seq_cst) volatile noexcept;
291 floating-point-type exchange(floating-point-type,
292 memory_order = memory_order::seq_cst) noexcept;
293 bool compare_exchange_weak(floating-point-type&, floating-point-type,
294 memory_order, memory_order) volatile noexcept;
295 bool compare_exchange_weak(floating-point-type&, floating-point-type,
296 memory_order, memory_order) noexcept;
297 bool compare_exchange_strong(floating-point-type&, floating-point-type,
298 memory_order, memory_order) volatile noexcept;
299 bool compare_exchange_strong(floating-point-type&, floating-point-type,
300 memory_order, memory_order) noexcept;
301 bool compare_exchange_weak(floating-point-type&, floating-point-type,
302 memory_order = memory_order::seq_cst) volatile noexcept;
303 bool compare_exchange_weak(floating-point-type&, floating-point-type,
304 memory_order = memory_order::seq_cst) noexcept;
305 bool compare_exchange_strong(floating-point-type&, floating-point-type,
306 memory_order = memory_order::seq_cst) volatile noexcept;
307 bool compare_exchange_strong(floating-point-type&, floating-point-type,
308 memory_order = memory_order::seq_cst) noexcept;
309
310 floating-point-type fetch_add(floating-point-type,
311 memory_order = memory_order::seq_cst) volatile noexcept;
312 floating-point-type fetch_add(floating-point-type,
313 memory_order = memory_order::seq_cst) noexcept;
314 floating-point-type fetch_sub(floating-point-type,
315 memory_order = memory_order::seq_cst) volatile noexcept;
316 floating-point-type fetch_sub(floating-point-type,
317 memory_order = memory_order::seq_cst) noexcept;
318
319 floating-point-type operator+=(floating-point-type) volatile noexcept;
320 floating-point-type operator+=(floating-point-type) noexcept;
321 floating-point-type operator-=(floating-point-type) volatile noexcept;
322 floating-point-type operator-=(floating-point-type) noexcept;
323
324 void wait(floating-point-type, memory_order = memory_order::seq_cst) const volatile noexcept;
325 void wait(floating-point-type, memory_order = memory_order::seq_cst) const noexcept;
326 void notify_one() volatile noexcept;
327 void notify_one() noexcept;
328 void notify_all() volatile noexcept;
329 void notify_all() noexcept;
330};
331
332// [atomics.nonmembers], non-member functions
333template<class T>
334 bool atomic_is_lock_free(const volatile atomic<T>*) noexcept;
335template<class T>
336 bool atomic_is_lock_free(const atomic<T>*) noexcept;
337template<class T>
338 void atomic_store(volatile atomic<T>*, atomic<T>::value_type) noexcept;
339template<class T>
340 void atomic_store(atomic<T>*, atomic<T>::value_type) noexcept;
341template<class T>
342 void atomic_store_explicit(volatile atomic<T>*, atomic<T>::value_type,
343 memory_order) noexcept;
344template<class T>
345 void atomic_store_explicit(atomic<T>*, atomic<T>::value_type,
346 memory_order) noexcept;
347template<class T>
348 T atomic_load(const volatile atomic<T>*) noexcept;
349template<class T>
350 T atomic_load(const atomic<T>*) noexcept;
351template<class T>
352 T atomic_load_explicit(const volatile atomic<T>*, memory_order) noexcept;
353template<class T>
354 T atomic_load_explicit(const atomic<T>*, memory_order) noexcept;
355template<class T>
356 T atomic_exchange(volatile atomic<T>*, atomic<T>::value_type) noexcept;
357template<class T>
358 T atomic_exchange(atomic<T>*, atomic<T>::value_type) noexcept;
359template<class T>
360 T atomic_exchange_explicit(volatile atomic<T>*, atomic<T>::value_type,
361 memory_order) noexcept;
362template<class T>
363 T atomic_exchange_explicit(atomic<T>*, atomic<T>::value_type,
364 memory_order) noexcept;
365template<class T>
366 bool atomic_compare_exchange_weak(volatile atomic<T>*, atomic<T>::value_type*,
367 atomic<T>::value_type) noexcept;
368template<class T>
369 bool atomic_compare_exchange_weak(atomic<T>*, atomic<T>::value_type*,
370 atomic<T>::value_type) noexcept;
371template<class T>
372 bool atomic_compare_exchange_strong(volatile atomic<T>*, atomic<T>::value_type*,
373 atomic<T>::value_type) noexcept;
374template<class T>
375 bool atomic_compare_exchange_strong(atomic<T>*, atomic<T>::value_type*,
376 atomic<T>::value_type) noexcept;
377template<class T>
378 bool atomic_compare_exchange_weak_explicit(volatile atomic<T>*, atomic<T>::value_type*,
379 atomic<T>::value_type,
380 memory_order, memory_order) noexcept;
381template<class T>
382 bool atomic_compare_exchange_weak_explicit(atomic<T>*, atomic<T>::value_type*,
383 atomic<T>::value_type,
384 memory_order, memory_order) noexcept;
385template<class T>
386 bool atomic_compare_exchange_strong_explicit(volatile atomic<T>*, atomic<T>::value_type*,
387 atomic<T>::value_type,
388 memory_order, memory_order) noexcept;
389template<class T>
390 bool atomic_compare_exchange_strong_explicit(atomic<T>*, atomic<T>::value_type*,
391 atomic<T>::value_type,
392 memory_order, memory_order) noexcept;
393
394template<class T>
395 T atomic_fetch_add(volatile atomic<T>*, atomic<T>::difference_type) noexcept;
396template<class T>
397 T atomic_fetch_add(atomic<T>*, atomic<T>::difference_type) noexcept;
398template<class T>
399 T atomic_fetch_add_explicit(volatile atomic<T>*, atomic<T>::difference_type,
400 memory_order) noexcept;
401template<class T>
402 T atomic_fetch_add_explicit(atomic<T>*, atomic<T>::difference_type,
403 memory_order) noexcept;
404template<class T>
405 T atomic_fetch_sub(volatile atomic<T>*, atomic<T>::difference_type) noexcept;
406template<class T>
407 T atomic_fetch_sub(atomic<T>*, atomic<T>::difference_type) noexcept;
408template<class T>
409 T atomic_fetch_sub_explicit(volatile atomic<T>*, atomic<T>::difference_type,
410 memory_order) noexcept;
411template<class T>
412 T atomic_fetch_sub_explicit(atomic<T>*, atomic<T>::difference_type,
413 memory_order) noexcept;
414template<class T>
415 T atomic_fetch_and(volatile atomic<T>*, atomic<T>::value_type) noexcept;
416template<class T>
417 T atomic_fetch_and(atomic<T>*, atomic<T>::value_type) noexcept;
418template<class T>
419 T atomic_fetch_and_explicit(volatile atomic<T>*, atomic<T>::value_type,
420 memory_order) noexcept;
421template<class T>
422 T atomic_fetch_and_explicit(atomic<T>*, atomic<T>::value_type,
423 memory_order) noexcept;
424template<class T>
425 T atomic_fetch_or(volatile atomic<T>*, atomic<T>::value_type) noexcept;
426template<class T>
427 T atomic_fetch_or(atomic<T>*, atomic<T>::value_type) noexcept;
428template<class T>
429 T atomic_fetch_or_explicit(volatile atomic<T>*, atomic<T>::value_type,
430 memory_order) noexcept;
431template<class T>
432 T atomic_fetch_or_explicit(atomic<T>*, atomic<T>::value_type,
433 memory_order) noexcept;
434template<class T>
435 T atomic_fetch_xor(volatile atomic<T>*, atomic<T>::value_type) noexcept;
436template<class T>
437 T atomic_fetch_xor(atomic<T>*, atomic<T>::value_type) noexcept;
438template<class T>
439 T atomic_fetch_xor_explicit(volatile atomic<T>*, atomic<T>::value_type,
440 memory_order) noexcept;
441template<class T>
442 T atomic_fetch_xor_explicit(atomic<T>*, atomic<T>::value_type,
443 memory_order) noexcept;
444
445template<class T>
446 void atomic_wait(const volatile atomic<T>*, atomic<T>::value_type) noexcept;
447template<class T>
448 void atomic_wait(const atomic<T>*, atomic<T>::value_type) noexcept;
449template<class T>
450 void atomic_wait_explicit(const volatile atomic<T>*, atomic<T>::value_type,
451 memory_order) noexcept;
452template<class T>
453 void atomic_wait_explicit(const atomic<T>*, atomic<T>::value_type,
454 memory_order) noexcept;
455template<class T>
456 void atomic_notify_one(volatile atomic<T>*) noexcept;
457template<class T>
458 void atomic_notify_one(atomic<T>*) noexcept;
459template<class T>
460 void atomic_notify_all(volatile atomic<T>*) noexcept;
461template<class T>
462 void atomic_notify_all(atomic<T>*) noexcept;
463
464// Atomics for standard typedef types
465
466typedef atomic<bool> atomic_bool;
467typedef atomic<char> atomic_char;
468typedef atomic<signed char> atomic_schar;
469typedef atomic<unsigned char> atomic_uchar;
470typedef atomic<short> atomic_short;
471typedef atomic<unsigned short> atomic_ushort;
472typedef atomic<int> atomic_int;
473typedef atomic<unsigned int> atomic_uint;
474typedef atomic<long> atomic_long;
475typedef atomic<unsigned long> atomic_ulong;
476typedef atomic<long long> atomic_llong;
477typedef atomic<unsigned long long> atomic_ullong;
478typedef atomic<char8_t> atomic_char8_t; // C++20
479typedef atomic<char16_t> atomic_char16_t;
480typedef atomic<char32_t> atomic_char32_t;
481typedef atomic<wchar_t> atomic_wchar_t;
482
483typedef atomic<int_least8_t> atomic_int_least8_t;
484typedef atomic<uint_least8_t> atomic_uint_least8_t;
485typedef atomic<int_least16_t> atomic_int_least16_t;
486typedef atomic<uint_least16_t> atomic_uint_least16_t;
487typedef atomic<int_least32_t> atomic_int_least32_t;
488typedef atomic<uint_least32_t> atomic_uint_least32_t;
489typedef atomic<int_least64_t> atomic_int_least64_t;
490typedef atomic<uint_least64_t> atomic_uint_least64_t;
491
492typedef atomic<int_fast8_t> atomic_int_fast8_t;
493typedef atomic<uint_fast8_t> atomic_uint_fast8_t;
494typedef atomic<int_fast16_t> atomic_int_fast16_t;
495typedef atomic<uint_fast16_t> atomic_uint_fast16_t;
496typedef atomic<int_fast32_t> atomic_int_fast32_t;
497typedef atomic<uint_fast32_t> atomic_uint_fast32_t;
498typedef atomic<int_fast64_t> atomic_int_fast64_t;
499typedef atomic<uint_fast64_t> atomic_uint_fast64_t;
500
501typedef atomic<int8_t> atomic_int8_t;
502typedef atomic<uint8_t> atomic_uint8_t;
503typedef atomic<int16_t> atomic_int16_t;
504typedef atomic<uint16_t> atomic_uint16_t;
505typedef atomic<int32_t> atomic_int32_t;
506typedef atomic<uint32_t> atomic_uint32_t;
507typedef atomic<int64_t> atomic_int64_t;
508typedef atomic<uint64_t> atomic_uint64_t;
509
510typedef atomic<intptr_t> atomic_intptr_t;
511typedef atomic<uintptr_t> atomic_uintptr_t;
512typedef atomic<size_t> atomic_size_t;
513typedef atomic<ptrdiff_t> atomic_ptrdiff_t;
514typedef atomic<intmax_t> atomic_intmax_t;
515typedef atomic<uintmax_t> atomic_uintmax_t;
516
517typedef see-below atomic_signed_lock_free; // since C++20
518typedef see-below atomic_unsigned_lock_free; // since C++20
519
520// flag type and operations
521
522typedef struct atomic_flag
523{
524 atomic_flag() noexcept = default; // until C++20
525 constexpr atomic_flag() noexcept; // since C++20
526 atomic_flag(const atomic_flag&) = delete;
527 atomic_flag& operator=(const atomic_flag&) = delete;
528 atomic_flag& operator=(const atomic_flag&) volatile = delete;
529
530 bool test(memory_order m = memory_order_seq_cst) volatile noexcept;
531 bool test(memory_order m = memory_order_seq_cst) noexcept;
532 bool test_and_set(memory_order m = memory_order_seq_cst) volatile noexcept;
533 bool test_and_set(memory_order m = memory_order_seq_cst) noexcept;
534 void clear(memory_order m = memory_order_seq_cst) volatile noexcept;
535 void clear(memory_order m = memory_order_seq_cst) noexcept;
536
537 void wait(bool, memory_order = memory_order::seq_cst) const volatile noexcept;
538 void wait(bool, memory_order = memory_order::seq_cst) const noexcept;
539 void notify_one() volatile noexcept;
540 void notify_one() noexcept;
541 void notify_all() volatile noexcept;
542 void notify_all() noexcept;
543} atomic_flag;
544
545bool atomic_flag_test(volatile atomic_flag* obj) noexcept;
546bool atomic_flag_test(atomic_flag* obj) noexcept;
547bool atomic_flag_test_explicit(volatile atomic_flag* obj,
548 memory_order m) noexcept;
549bool atomic_flag_test_explicit(atomic_flag* obj, memory_order m) noexcept;
550bool atomic_flag_test_and_set(volatile atomic_flag* obj) noexcept;
551bool atomic_flag_test_and_set(atomic_flag* obj) noexcept;
552bool atomic_flag_test_and_set_explicit(volatile atomic_flag* obj,
553 memory_order m) noexcept;
554bool atomic_flag_test_and_set_explicit(atomic_flag* obj, memory_order m) noexcept;
555void atomic_flag_clear(volatile atomic_flag* obj) noexcept;
556void atomic_flag_clear(atomic_flag* obj) noexcept;
557void atomic_flag_clear_explicit(volatile atomic_flag* obj, memory_order m) noexcept;
558void atomic_flag_clear_explicit(atomic_flag* obj, memory_order m) noexcept;
559
560void atomic_wait(const volatile atomic_flag* obj, T old) noexcept;
561void atomic_wait(const atomic_flag* obj, T old) noexcept;
562void atomic_wait_explicit(const volatile atomic_flag* obj, T old, memory_order m) noexcept;
563void atomic_wait_explicit(const atomic_flag* obj, T old, memory_order m) noexcept;
564void atomic_one(volatile atomic_flag* obj) noexcept;
565void atomic_one(atomic_flag* obj) noexcept;
566void atomic_all(volatile atomic_flag* obj) noexcept;
567void atomic_all(atomic_flag* obj) noexcept;
568
569// fences
570
571void atomic_thread_fence(memory_order m) noexcept;
572void atomic_signal_fence(memory_order m) noexcept;
573
574// deprecated
575
576template <class T>
577 void atomic_init(volatile atomic<T>* obj, atomic<T>::value_type desr) noexcept;
578
579template <class T>
580 void atomic_init(atomic<T>* obj, atomic<T>::value_type desr) noexcept;
581
582#define ATOMIC_VAR_INIT(value) see below
583
584#define ATOMIC_FLAG_INIT see below
585
586} // std
587
588*/
589
590#include <__config>
591
592#if _LIBCPP_STD_VER < 23 && defined(_LIBCPP_STDATOMIC_H)
593# error <atomic> is incompatible with <stdatomic.h> before C++23. Please compile with -std=c++23.
594#endif
595
596#include <__atomic/aliases.h>
597#include <__atomic/atomic.h>
598#include <__atomic/atomic_base.h>
599#include <__atomic/atomic_flag.h>
600#include <__atomic/atomic_init.h>
601#include <__atomic/atomic_lock_free.h>
602#include <__atomic/atomic_sync.h>
603#include <__atomic/check_memory_order.h>
604#include <__atomic/contention_t.h>
605#include <__atomic/cxx_atomic_impl.h>
606#include <__atomic/fence.h>
607#include <__atomic/is_always_lock_free.h>
608#include <__atomic/kill_dependency.h>
609#include <__atomic/memory_order.h>
610#include <version>
611
612#if _LIBCPP_STD_VER >= 20
613# include <__atomic/atomic_ref.h>
614#endif
615
616#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
617# pragma GCC system_header
618#endif
619
620#ifdef _LIBCPP_HAS_NO_ATOMIC_HEADER
621# error <atomic> is not implemented
622#endif
623
624#if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20
625# include <cmath>
626# include <compare>
627# include <cstdlib>
628# include <cstring>
629# include <type_traits>
630#endif
631
632#endif // _LIBCPP_ATOMIC
633