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 <__assert> // all public C++ headers provide the assertion handler
591#include <__atomic/aliases.h>
592#include <__atomic/atomic.h>
593#include <__atomic/atomic_base.h>
594#include <__atomic/atomic_flag.h>
595#include <__atomic/atomic_init.h>
596#include <__atomic/atomic_lock_free.h>
597#include <__atomic/atomic_sync.h>
598#include <__atomic/check_memory_order.h>
599#include <__atomic/contention_t.h>
600#include <__atomic/cxx_atomic_impl.h>
601#include <__atomic/fence.h>
602#include <__atomic/is_always_lock_free.h>
603#include <__atomic/kill_dependency.h>
604#include <__atomic/memory_order.h>
605#include <__config>
606#include <version>
607
608#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
609#  pragma GCC system_header
610#endif
611
612#ifdef _LIBCPP_HAS_NO_ATOMIC_HEADER
613#  error <atomic> is not implemented
614#endif
615
616#ifdef kill_dependency
617#  error <atomic> is incompatible with <stdatomic.h> before C++23. Please compile with -std=c++23.
618#endif
619
620#if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20
621#  include <cmath>
622#  include <compare>
623#  include <cstring>
624#  include <type_traits>
625#endif
626
627#endif // _LIBCPP_ATOMIC
628