xref: /freebsd/contrib/llvm-project/libcxx/include/atomic (revision 06c3fb2749bda94cb5201f81ffdb8fa6c3161b2e)
10b57cec5SDimitry Andric// -*- C++ -*-
2349cc55cSDimitry Andric//===----------------------------------------------------------------------===//
30b57cec5SDimitry Andric//
40b57cec5SDimitry Andric// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
50b57cec5SDimitry Andric// See https://llvm.org/LICENSE.txt for license information.
60b57cec5SDimitry Andric// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
70b57cec5SDimitry Andric//
80b57cec5SDimitry Andric//===----------------------------------------------------------------------===//
90b57cec5SDimitry Andric
100b57cec5SDimitry Andric#ifndef _LIBCPP_ATOMIC
110b57cec5SDimitry Andric#define _LIBCPP_ATOMIC
120b57cec5SDimitry Andric
130b57cec5SDimitry Andric/*
140b57cec5SDimitry Andric    atomic synopsis
150b57cec5SDimitry Andric
160b57cec5SDimitry Andricnamespace std
170b57cec5SDimitry Andric{
180b57cec5SDimitry Andric
19e8d8bef9SDimitry Andric// feature test macro [version.syn]
200b57cec5SDimitry Andric
21e8d8bef9SDimitry Andric#define __cpp_lib_atomic_is_always_lock_free
22e8d8bef9SDimitry Andric#define __cpp_lib_atomic_flag_test
23e8d8bef9SDimitry Andric#define __cpp_lib_atomic_lock_free_type_aliases
24e8d8bef9SDimitry Andric#define __cpp_lib_atomic_wait
250b57cec5SDimitry Andric
260b57cec5SDimitry Andric // order and consistency
270b57cec5SDimitry Andric
280b57cec5SDimitry Andric enum memory_order: unspecified // enum class in C++20
290b57cec5SDimitry Andric {
300b57cec5SDimitry Andric    relaxed,
310b57cec5SDimitry Andric    consume, // load-consume
320b57cec5SDimitry Andric    acquire, // load-acquire
330b57cec5SDimitry Andric    release, // store-release
340b57cec5SDimitry Andric    acq_rel, // store-release load-acquire
350b57cec5SDimitry Andric    seq_cst // store-release load-acquire
360b57cec5SDimitry Andric };
370b57cec5SDimitry Andric
380b57cec5SDimitry Andric inline constexpr auto memory_order_relaxed = memory_order::relaxed;
390b57cec5SDimitry Andric inline constexpr auto memory_order_consume = memory_order::consume;
400b57cec5SDimitry Andric inline constexpr auto memory_order_acquire = memory_order::acquire;
410b57cec5SDimitry Andric inline constexpr auto memory_order_release = memory_order::release;
420b57cec5SDimitry Andric inline constexpr auto memory_order_acq_rel = memory_order::acq_rel;
430b57cec5SDimitry Andric inline constexpr auto memory_order_seq_cst = memory_order::seq_cst;
440b57cec5SDimitry Andric
450b57cec5SDimitry Andrictemplate <class T> T kill_dependency(T y) noexcept;
460b57cec5SDimitry Andric
470b57cec5SDimitry Andric// lock-free property
480b57cec5SDimitry Andric
490b57cec5SDimitry Andric#define ATOMIC_BOOL_LOCK_FREE unspecified
500b57cec5SDimitry Andric#define ATOMIC_CHAR_LOCK_FREE unspecified
51e8d8bef9SDimitry Andric#define ATOMIC_CHAR8_T_LOCK_FREE unspecified // C++20
520b57cec5SDimitry Andric#define ATOMIC_CHAR16_T_LOCK_FREE unspecified
530b57cec5SDimitry Andric#define ATOMIC_CHAR32_T_LOCK_FREE unspecified
540b57cec5SDimitry Andric#define ATOMIC_WCHAR_T_LOCK_FREE unspecified
550b57cec5SDimitry Andric#define ATOMIC_SHORT_LOCK_FREE unspecified
560b57cec5SDimitry Andric#define ATOMIC_INT_LOCK_FREE unspecified
570b57cec5SDimitry Andric#define ATOMIC_LONG_LOCK_FREE unspecified
580b57cec5SDimitry Andric#define ATOMIC_LLONG_LOCK_FREE unspecified
590b57cec5SDimitry Andric#define ATOMIC_POINTER_LOCK_FREE unspecified
600b57cec5SDimitry Andric
610b57cec5SDimitry Andrictemplate <class T>
620b57cec5SDimitry Andricstruct atomic
630b57cec5SDimitry Andric{
645ffd83dbSDimitry Andric    using value_type = T;
655ffd83dbSDimitry Andric
660b57cec5SDimitry Andric    static constexpr bool is_always_lock_free;
670b57cec5SDimitry Andric    bool is_lock_free() const volatile noexcept;
680b57cec5SDimitry Andric    bool is_lock_free() const noexcept;
695ffd83dbSDimitry Andric
70fe6060f1SDimitry Andric    atomic() noexcept = default; // until C++20
71fe6060f1SDimitry Andric    constexpr atomic() noexcept(is_nothrow_default_constructible_v<T>); // since C++20
725ffd83dbSDimitry Andric    constexpr atomic(T desr) noexcept;
735ffd83dbSDimitry Andric    atomic(const atomic&) = delete;
745ffd83dbSDimitry Andric    atomic& operator=(const atomic&) = delete;
755ffd83dbSDimitry Andric    atomic& operator=(const atomic&) volatile = delete;
765ffd83dbSDimitry Andric
770b57cec5SDimitry Andric    T load(memory_order m = memory_order_seq_cst) const volatile noexcept;
780b57cec5SDimitry Andric    T load(memory_order m = memory_order_seq_cst) const noexcept;
790b57cec5SDimitry Andric    operator T() const volatile noexcept;
800b57cec5SDimitry Andric    operator T() const noexcept;
815ffd83dbSDimitry Andric    void store(T desr, memory_order m = memory_order_seq_cst) volatile noexcept;
825ffd83dbSDimitry Andric    void store(T desr, memory_order m = memory_order_seq_cst) noexcept;
835ffd83dbSDimitry Andric    T operator=(T) volatile noexcept;
845ffd83dbSDimitry Andric    T operator=(T) noexcept;
855ffd83dbSDimitry Andric
860b57cec5SDimitry Andric    T exchange(T desr, memory_order m = memory_order_seq_cst) volatile noexcept;
870b57cec5SDimitry Andric    T exchange(T desr, memory_order m = memory_order_seq_cst) noexcept;
880b57cec5SDimitry Andric    bool compare_exchange_weak(T& expc, T desr,
890b57cec5SDimitry Andric                               memory_order s, memory_order f) volatile noexcept;
900b57cec5SDimitry Andric    bool compare_exchange_weak(T& expc, T desr, memory_order s, memory_order f) noexcept;
910b57cec5SDimitry Andric    bool compare_exchange_strong(T& expc, T desr,
920b57cec5SDimitry Andric                                 memory_order s, memory_order f) volatile noexcept;
930b57cec5SDimitry Andric    bool compare_exchange_strong(T& expc, T desr,
940b57cec5SDimitry Andric                                 memory_order s, memory_order f) noexcept;
950b57cec5SDimitry Andric    bool compare_exchange_weak(T& expc, T desr,
960b57cec5SDimitry Andric                               memory_order m = memory_order_seq_cst) volatile noexcept;
970b57cec5SDimitry Andric    bool compare_exchange_weak(T& expc, T desr,
980b57cec5SDimitry Andric                               memory_order m = memory_order_seq_cst) noexcept;
990b57cec5SDimitry Andric    bool compare_exchange_strong(T& expc, T desr,
1000b57cec5SDimitry Andric                                memory_order m = memory_order_seq_cst) volatile noexcept;
1010b57cec5SDimitry Andric    bool compare_exchange_strong(T& expc, T desr,
1020b57cec5SDimitry Andric                                 memory_order m = memory_order_seq_cst) noexcept;
1030b57cec5SDimitry Andric
1045ffd83dbSDimitry Andric    void wait(T, memory_order = memory_order::seq_cst) const volatile noexcept;
1055ffd83dbSDimitry Andric    void wait(T, memory_order = memory_order::seq_cst) const noexcept;
1065ffd83dbSDimitry Andric    void notify_one() volatile noexcept;
1075ffd83dbSDimitry Andric    void notify_one() noexcept;
1085ffd83dbSDimitry Andric    void notify_all() volatile noexcept;
1095ffd83dbSDimitry Andric    void notify_all() noexcept;
1100b57cec5SDimitry Andric};
1110b57cec5SDimitry Andric
1120b57cec5SDimitry Andrictemplate <>
1130b57cec5SDimitry Andricstruct atomic<integral>
1140b57cec5SDimitry Andric{
1155ffd83dbSDimitry Andric    using value_type = integral;
116e8d8bef9SDimitry Andric    using difference_type = value_type;
1175ffd83dbSDimitry Andric
1180b57cec5SDimitry Andric    static constexpr bool is_always_lock_free;
1190b57cec5SDimitry Andric    bool is_lock_free() const volatile noexcept;
1200b57cec5SDimitry Andric    bool is_lock_free() const noexcept;
1215ffd83dbSDimitry Andric
1225ffd83dbSDimitry Andric    atomic() noexcept = default;
1235ffd83dbSDimitry Andric    constexpr atomic(integral desr) noexcept;
1245ffd83dbSDimitry Andric    atomic(const atomic&) = delete;
1255ffd83dbSDimitry Andric    atomic& operator=(const atomic&) = delete;
1265ffd83dbSDimitry Andric    atomic& operator=(const atomic&) volatile = delete;
1275ffd83dbSDimitry Andric
1280b57cec5SDimitry Andric    integral load(memory_order m = memory_order_seq_cst) const volatile noexcept;
1290b57cec5SDimitry Andric    integral load(memory_order m = memory_order_seq_cst) const noexcept;
1300b57cec5SDimitry Andric    operator integral() const volatile noexcept;
1310b57cec5SDimitry Andric    operator integral() const noexcept;
1325ffd83dbSDimitry Andric    void store(integral desr, memory_order m = memory_order_seq_cst) volatile noexcept;
1335ffd83dbSDimitry Andric    void store(integral desr, memory_order m = memory_order_seq_cst) noexcept;
1345ffd83dbSDimitry Andric    integral operator=(integral desr) volatile noexcept;
1355ffd83dbSDimitry Andric    integral operator=(integral desr) noexcept;
1365ffd83dbSDimitry Andric
1370b57cec5SDimitry Andric    integral exchange(integral desr,
1380b57cec5SDimitry Andric                      memory_order m = memory_order_seq_cst) volatile noexcept;
1390b57cec5SDimitry Andric    integral exchange(integral desr, memory_order m = memory_order_seq_cst) noexcept;
1400b57cec5SDimitry Andric    bool compare_exchange_weak(integral& expc, integral desr,
1410b57cec5SDimitry Andric                               memory_order s, memory_order f) volatile noexcept;
1420b57cec5SDimitry Andric    bool compare_exchange_weak(integral& expc, integral desr,
1430b57cec5SDimitry Andric                               memory_order s, memory_order f) noexcept;
1440b57cec5SDimitry Andric    bool compare_exchange_strong(integral& expc, integral desr,
1450b57cec5SDimitry Andric                                 memory_order s, memory_order f) volatile noexcept;
1460b57cec5SDimitry Andric    bool compare_exchange_strong(integral& expc, integral desr,
1470b57cec5SDimitry Andric                                 memory_order s, memory_order f) noexcept;
1480b57cec5SDimitry Andric    bool compare_exchange_weak(integral& expc, integral desr,
1490b57cec5SDimitry Andric                               memory_order m = memory_order_seq_cst) volatile noexcept;
1500b57cec5SDimitry Andric    bool compare_exchange_weak(integral& expc, integral desr,
1510b57cec5SDimitry Andric                               memory_order m = memory_order_seq_cst) noexcept;
1520b57cec5SDimitry Andric    bool compare_exchange_strong(integral& expc, integral desr,
1530b57cec5SDimitry Andric                                memory_order m = memory_order_seq_cst) volatile noexcept;
1540b57cec5SDimitry Andric    bool compare_exchange_strong(integral& expc, integral desr,
1550b57cec5SDimitry Andric                                 memory_order m = memory_order_seq_cst) noexcept;
1560b57cec5SDimitry Andric
1575ffd83dbSDimitry Andric    integral fetch_add(integral op, memory_order m = memory_order_seq_cst) volatile noexcept;
1580b57cec5SDimitry Andric    integral fetch_add(integral op, memory_order m = memory_order_seq_cst) noexcept;
1595ffd83dbSDimitry Andric    integral fetch_sub(integral op, memory_order m = memory_order_seq_cst) volatile noexcept;
1600b57cec5SDimitry Andric    integral fetch_sub(integral op, memory_order m = memory_order_seq_cst) noexcept;
1615ffd83dbSDimitry Andric    integral fetch_and(integral op, memory_order m = memory_order_seq_cst) volatile noexcept;
1620b57cec5SDimitry Andric    integral fetch_and(integral op, memory_order m = memory_order_seq_cst) noexcept;
1635ffd83dbSDimitry Andric    integral fetch_or(integral op, memory_order m = memory_order_seq_cst) volatile noexcept;
1640b57cec5SDimitry Andric    integral fetch_or(integral op, memory_order m = memory_order_seq_cst) noexcept;
1655ffd83dbSDimitry Andric    integral fetch_xor(integral op, memory_order m = memory_order_seq_cst) volatile noexcept;
1660b57cec5SDimitry Andric    integral fetch_xor(integral op, memory_order m = memory_order_seq_cst) noexcept;
1670b57cec5SDimitry Andric
1680b57cec5SDimitry Andric    integral operator++(int) volatile noexcept;
1690b57cec5SDimitry Andric    integral operator++(int) noexcept;
1700b57cec5SDimitry Andric    integral operator--(int) volatile noexcept;
1710b57cec5SDimitry Andric    integral operator--(int) noexcept;
1720b57cec5SDimitry Andric    integral operator++() volatile noexcept;
1730b57cec5SDimitry Andric    integral operator++() noexcept;
1740b57cec5SDimitry Andric    integral operator--() volatile noexcept;
1750b57cec5SDimitry Andric    integral operator--() noexcept;
1760b57cec5SDimitry Andric    integral operator+=(integral op) volatile noexcept;
1770b57cec5SDimitry Andric    integral operator+=(integral op) noexcept;
1780b57cec5SDimitry Andric    integral operator-=(integral op) volatile noexcept;
1790b57cec5SDimitry Andric    integral operator-=(integral op) noexcept;
1800b57cec5SDimitry Andric    integral operator&=(integral op) volatile noexcept;
1810b57cec5SDimitry Andric    integral operator&=(integral op) noexcept;
1820b57cec5SDimitry Andric    integral operator|=(integral op) volatile noexcept;
1830b57cec5SDimitry Andric    integral operator|=(integral op) noexcept;
1840b57cec5SDimitry Andric    integral operator^=(integral op) volatile noexcept;
1850b57cec5SDimitry Andric    integral operator^=(integral op) noexcept;
1865ffd83dbSDimitry Andric
1875ffd83dbSDimitry Andric    void wait(integral, memory_order = memory_order::seq_cst) const volatile noexcept;
1885ffd83dbSDimitry Andric    void wait(integral, memory_order = memory_order::seq_cst) const noexcept;
1895ffd83dbSDimitry Andric    void notify_one() volatile noexcept;
1905ffd83dbSDimitry Andric    void notify_one() noexcept;
1915ffd83dbSDimitry Andric    void notify_all() volatile noexcept;
1925ffd83dbSDimitry Andric    void notify_all() noexcept;
1930b57cec5SDimitry Andric};
1940b57cec5SDimitry Andric
1950b57cec5SDimitry Andrictemplate <class T>
1960b57cec5SDimitry Andricstruct atomic<T*>
1970b57cec5SDimitry Andric{
1985ffd83dbSDimitry Andric    using value_type = T*;
199e8d8bef9SDimitry Andric    using difference_type = ptrdiff_t;
2005ffd83dbSDimitry Andric
2010b57cec5SDimitry Andric    static constexpr bool is_always_lock_free;
2020b57cec5SDimitry Andric    bool is_lock_free() const volatile noexcept;
2030b57cec5SDimitry Andric    bool is_lock_free() const noexcept;
2045ffd83dbSDimitry Andric
205fe6060f1SDimitry Andric    atomic() noexcept = default; // until C++20
206fe6060f1SDimitry Andric    constexpr atomic() noexcept; // since C++20
2075ffd83dbSDimitry Andric    constexpr atomic(T* desr) noexcept;
2085ffd83dbSDimitry Andric    atomic(const atomic&) = delete;
2095ffd83dbSDimitry Andric    atomic& operator=(const atomic&) = delete;
2105ffd83dbSDimitry Andric    atomic& operator=(const atomic&) volatile = delete;
2115ffd83dbSDimitry Andric
2120b57cec5SDimitry Andric    T* load(memory_order m = memory_order_seq_cst) const volatile noexcept;
2130b57cec5SDimitry Andric    T* load(memory_order m = memory_order_seq_cst) const noexcept;
2140b57cec5SDimitry Andric    operator T*() const volatile noexcept;
2150b57cec5SDimitry Andric    operator T*() const noexcept;
2165ffd83dbSDimitry Andric    void store(T* desr, memory_order m = memory_order_seq_cst) volatile noexcept;
2175ffd83dbSDimitry Andric    void store(T* desr, memory_order m = memory_order_seq_cst) noexcept;
2185ffd83dbSDimitry Andric    T* operator=(T*) volatile noexcept;
2195ffd83dbSDimitry Andric    T* operator=(T*) noexcept;
2205ffd83dbSDimitry Andric
2210b57cec5SDimitry Andric    T* exchange(T* desr, memory_order m = memory_order_seq_cst) volatile noexcept;
2220b57cec5SDimitry Andric    T* exchange(T* desr, memory_order m = memory_order_seq_cst) noexcept;
2230b57cec5SDimitry Andric    bool compare_exchange_weak(T*& expc, T* desr,
2240b57cec5SDimitry Andric                               memory_order s, memory_order f) volatile noexcept;
2250b57cec5SDimitry Andric    bool compare_exchange_weak(T*& expc, T* desr,
2260b57cec5SDimitry Andric                               memory_order s, memory_order f) noexcept;
2270b57cec5SDimitry Andric    bool compare_exchange_strong(T*& expc, T* desr,
2280b57cec5SDimitry Andric                                 memory_order s, memory_order f) volatile noexcept;
2290b57cec5SDimitry Andric    bool compare_exchange_strong(T*& expc, T* desr,
2300b57cec5SDimitry Andric                                 memory_order s, memory_order f) noexcept;
2310b57cec5SDimitry Andric    bool compare_exchange_weak(T*& expc, T* desr,
2320b57cec5SDimitry Andric                               memory_order m = memory_order_seq_cst) volatile noexcept;
2330b57cec5SDimitry Andric    bool compare_exchange_weak(T*& expc, T* desr,
2340b57cec5SDimitry Andric                               memory_order m = memory_order_seq_cst) noexcept;
2350b57cec5SDimitry Andric    bool compare_exchange_strong(T*& expc, T* desr,
2360b57cec5SDimitry Andric                                memory_order m = memory_order_seq_cst) volatile noexcept;
2370b57cec5SDimitry Andric    bool compare_exchange_strong(T*& expc, T* desr,
2380b57cec5SDimitry Andric                                 memory_order m = memory_order_seq_cst) noexcept;
2390b57cec5SDimitry Andric    T* fetch_add(ptrdiff_t op, memory_order m = memory_order_seq_cst) volatile noexcept;
2400b57cec5SDimitry Andric    T* fetch_add(ptrdiff_t op, memory_order m = memory_order_seq_cst) noexcept;
2410b57cec5SDimitry Andric    T* fetch_sub(ptrdiff_t op, memory_order m = memory_order_seq_cst) volatile noexcept;
2420b57cec5SDimitry Andric    T* fetch_sub(ptrdiff_t op, memory_order m = memory_order_seq_cst) noexcept;
2430b57cec5SDimitry Andric
2440b57cec5SDimitry Andric    T* operator++(int) volatile noexcept;
2450b57cec5SDimitry Andric    T* operator++(int) noexcept;
2460b57cec5SDimitry Andric    T* operator--(int) volatile noexcept;
2470b57cec5SDimitry Andric    T* operator--(int) noexcept;
2480b57cec5SDimitry Andric    T* operator++() volatile noexcept;
2490b57cec5SDimitry Andric    T* operator++() noexcept;
2500b57cec5SDimitry Andric    T* operator--() volatile noexcept;
2510b57cec5SDimitry Andric    T* operator--() noexcept;
2520b57cec5SDimitry Andric    T* operator+=(ptrdiff_t op) volatile noexcept;
2530b57cec5SDimitry Andric    T* operator+=(ptrdiff_t op) noexcept;
2540b57cec5SDimitry Andric    T* operator-=(ptrdiff_t op) volatile noexcept;
2550b57cec5SDimitry Andric    T* operator-=(ptrdiff_t op) noexcept;
2565ffd83dbSDimitry Andric
2575ffd83dbSDimitry Andric    void wait(T*, memory_order = memory_order::seq_cst) const volatile noexcept;
2585ffd83dbSDimitry Andric    void wait(T*, memory_order = memory_order::seq_cst) const noexcept;
2595ffd83dbSDimitry Andric    void notify_one() volatile noexcept;
2605ffd83dbSDimitry Andric    void notify_one() noexcept;
2615ffd83dbSDimitry Andric    void notify_all() volatile noexcept;
2625ffd83dbSDimitry Andric    void notify_all() noexcept;
2630b57cec5SDimitry Andric};
2640b57cec5SDimitry Andric
2650b57cec5SDimitry Andric
266349cc55cSDimitry Andric// [atomics.nonmembers], non-member functions
2670b57cec5SDimitry Andrictemplate<class T>
268349cc55cSDimitry Andric  bool atomic_is_lock_free(const volatile atomic<T>*) noexcept;
269349cc55cSDimitry Andrictemplate<class T>
270349cc55cSDimitry Andric  bool atomic_is_lock_free(const atomic<T>*) noexcept;
271349cc55cSDimitry Andrictemplate<class T>
272349cc55cSDimitry Andric  void atomic_store(volatile atomic<T>*, atomic<T>::value_type) noexcept;
273349cc55cSDimitry Andrictemplate<class T>
274349cc55cSDimitry Andric  void atomic_store(atomic<T>*, atomic<T>::value_type) noexcept;
275349cc55cSDimitry Andrictemplate<class T>
276349cc55cSDimitry Andric  void atomic_store_explicit(volatile atomic<T>*, atomic<T>::value_type,
277349cc55cSDimitry Andric                             memory_order) noexcept;
278349cc55cSDimitry Andrictemplate<class T>
279349cc55cSDimitry Andric  void atomic_store_explicit(atomic<T>*, atomic<T>::value_type,
280349cc55cSDimitry Andric                             memory_order) noexcept;
281349cc55cSDimitry Andrictemplate<class T>
282349cc55cSDimitry Andric  T atomic_load(const volatile atomic<T>*) noexcept;
283349cc55cSDimitry Andrictemplate<class T>
284349cc55cSDimitry Andric  T atomic_load(const atomic<T>*) noexcept;
285349cc55cSDimitry Andrictemplate<class T>
286349cc55cSDimitry Andric  T atomic_load_explicit(const volatile atomic<T>*, memory_order) noexcept;
287349cc55cSDimitry Andrictemplate<class T>
288349cc55cSDimitry Andric  T atomic_load_explicit(const atomic<T>*, memory_order) noexcept;
289349cc55cSDimitry Andrictemplate<class T>
290349cc55cSDimitry Andric  T atomic_exchange(volatile atomic<T>*, atomic<T>::value_type) noexcept;
291349cc55cSDimitry Andrictemplate<class T>
292349cc55cSDimitry Andric  T atomic_exchange(atomic<T>*, atomic<T>::value_type) noexcept;
293349cc55cSDimitry Andrictemplate<class T>
294349cc55cSDimitry Andric  T atomic_exchange_explicit(volatile atomic<T>*, atomic<T>::value_type,
295349cc55cSDimitry Andric                             memory_order) noexcept;
296349cc55cSDimitry Andrictemplate<class T>
297349cc55cSDimitry Andric  T atomic_exchange_explicit(atomic<T>*, atomic<T>::value_type,
298349cc55cSDimitry Andric                             memory_order) noexcept;
299349cc55cSDimitry Andrictemplate<class T>
300349cc55cSDimitry Andric  bool atomic_compare_exchange_weak(volatile atomic<T>*, atomic<T>::value_type*,
301349cc55cSDimitry Andric                                    atomic<T>::value_type) noexcept;
302349cc55cSDimitry Andrictemplate<class T>
303349cc55cSDimitry Andric  bool atomic_compare_exchange_weak(atomic<T>*, atomic<T>::value_type*,
304349cc55cSDimitry Andric                                    atomic<T>::value_type) noexcept;
305349cc55cSDimitry Andrictemplate<class T>
306349cc55cSDimitry Andric  bool atomic_compare_exchange_strong(volatile atomic<T>*, atomic<T>::value_type*,
307349cc55cSDimitry Andric                                      atomic<T>::value_type) noexcept;
308349cc55cSDimitry Andrictemplate<class T>
309349cc55cSDimitry Andric  bool atomic_compare_exchange_strong(atomic<T>*, atomic<T>::value_type*,
310349cc55cSDimitry Andric                                      atomic<T>::value_type) noexcept;
311349cc55cSDimitry Andrictemplate<class T>
312349cc55cSDimitry Andric  bool atomic_compare_exchange_weak_explicit(volatile atomic<T>*, atomic<T>::value_type*,
313349cc55cSDimitry Andric                                             atomic<T>::value_type,
314349cc55cSDimitry Andric                                             memory_order, memory_order) noexcept;
315349cc55cSDimitry Andrictemplate<class T>
316349cc55cSDimitry Andric  bool atomic_compare_exchange_weak_explicit(atomic<T>*, atomic<T>::value_type*,
317349cc55cSDimitry Andric                                             atomic<T>::value_type,
318349cc55cSDimitry Andric                                             memory_order, memory_order) noexcept;
319349cc55cSDimitry Andrictemplate<class T>
320349cc55cSDimitry Andric  bool atomic_compare_exchange_strong_explicit(volatile atomic<T>*, atomic<T>::value_type*,
321349cc55cSDimitry Andric                                               atomic<T>::value_type,
322349cc55cSDimitry Andric                                               memory_order, memory_order) noexcept;
323349cc55cSDimitry Andrictemplate<class T>
324349cc55cSDimitry Andric  bool atomic_compare_exchange_strong_explicit(atomic<T>*, atomic<T>::value_type*,
325349cc55cSDimitry Andric                                               atomic<T>::value_type,
326349cc55cSDimitry Andric                                               memory_order, memory_order) noexcept;
3270b57cec5SDimitry Andric
3280b57cec5SDimitry Andrictemplate<class T>
329349cc55cSDimitry Andric  T atomic_fetch_add(volatile atomic<T>*, atomic<T>::difference_type) noexcept;
330349cc55cSDimitry Andrictemplate<class T>
331349cc55cSDimitry Andric  T atomic_fetch_add(atomic<T>*, atomic<T>::difference_type) noexcept;
332349cc55cSDimitry Andrictemplate<class T>
333349cc55cSDimitry Andric  T atomic_fetch_add_explicit(volatile atomic<T>*, atomic<T>::difference_type,
334349cc55cSDimitry Andric                              memory_order) noexcept;
335349cc55cSDimitry Andrictemplate<class T>
336349cc55cSDimitry Andric  T atomic_fetch_add_explicit(atomic<T>*, atomic<T>::difference_type,
337349cc55cSDimitry Andric                              memory_order) noexcept;
338349cc55cSDimitry Andrictemplate<class T>
339349cc55cSDimitry Andric  T atomic_fetch_sub(volatile atomic<T>*, atomic<T>::difference_type) noexcept;
340349cc55cSDimitry Andrictemplate<class T>
341349cc55cSDimitry Andric  T atomic_fetch_sub(atomic<T>*, atomic<T>::difference_type) noexcept;
342349cc55cSDimitry Andrictemplate<class T>
343349cc55cSDimitry Andric  T atomic_fetch_sub_explicit(volatile atomic<T>*, atomic<T>::difference_type,
344349cc55cSDimitry Andric                              memory_order) noexcept;
345349cc55cSDimitry Andrictemplate<class T>
346349cc55cSDimitry Andric  T atomic_fetch_sub_explicit(atomic<T>*, atomic<T>::difference_type,
347349cc55cSDimitry Andric                              memory_order) noexcept;
348349cc55cSDimitry Andrictemplate<class T>
349349cc55cSDimitry Andric  T atomic_fetch_and(volatile atomic<T>*, atomic<T>::value_type) noexcept;
350349cc55cSDimitry Andrictemplate<class T>
351349cc55cSDimitry Andric  T atomic_fetch_and(atomic<T>*, atomic<T>::value_type) noexcept;
352349cc55cSDimitry Andrictemplate<class T>
353349cc55cSDimitry Andric  T atomic_fetch_and_explicit(volatile atomic<T>*, atomic<T>::value_type,
354349cc55cSDimitry Andric                              memory_order) noexcept;
355349cc55cSDimitry Andrictemplate<class T>
356349cc55cSDimitry Andric  T atomic_fetch_and_explicit(atomic<T>*, atomic<T>::value_type,
357349cc55cSDimitry Andric                              memory_order) noexcept;
358349cc55cSDimitry Andrictemplate<class T>
359349cc55cSDimitry Andric  T atomic_fetch_or(volatile atomic<T>*, atomic<T>::value_type) noexcept;
360349cc55cSDimitry Andrictemplate<class T>
361349cc55cSDimitry Andric  T atomic_fetch_or(atomic<T>*, atomic<T>::value_type) noexcept;
362349cc55cSDimitry Andrictemplate<class T>
363349cc55cSDimitry Andric  T atomic_fetch_or_explicit(volatile atomic<T>*, atomic<T>::value_type,
364349cc55cSDimitry Andric                             memory_order) noexcept;
365349cc55cSDimitry Andrictemplate<class T>
366349cc55cSDimitry Andric  T atomic_fetch_or_explicit(atomic<T>*, atomic<T>::value_type,
367349cc55cSDimitry Andric                             memory_order) noexcept;
368349cc55cSDimitry Andrictemplate<class T>
369349cc55cSDimitry Andric  T atomic_fetch_xor(volatile atomic<T>*, atomic<T>::value_type) noexcept;
370349cc55cSDimitry Andrictemplate<class T>
371349cc55cSDimitry Andric  T atomic_fetch_xor(atomic<T>*, atomic<T>::value_type) noexcept;
372349cc55cSDimitry Andrictemplate<class T>
373349cc55cSDimitry Andric  T atomic_fetch_xor_explicit(volatile atomic<T>*, atomic<T>::value_type,
374349cc55cSDimitry Andric                              memory_order) noexcept;
375349cc55cSDimitry Andrictemplate<class T>
376349cc55cSDimitry Andric  T atomic_fetch_xor_explicit(atomic<T>*, atomic<T>::value_type,
377349cc55cSDimitry Andric                              memory_order) noexcept;
3780b57cec5SDimitry Andric
3790b57cec5SDimitry Andrictemplate<class T>
380bdd1243dSDimitry Andric  void atomic_wait(const volatile atomic<T>*, atomic<T>::value_type) noexcept;
3810b57cec5SDimitry Andrictemplate<class T>
382bdd1243dSDimitry Andric  void atomic_wait(const atomic<T>*, atomic<T>::value_type) noexcept;
3830b57cec5SDimitry Andrictemplate<class T>
384349cc55cSDimitry Andric  void atomic_wait_explicit(const volatile atomic<T>*, atomic<T>::value_type,
385bdd1243dSDimitry Andric                            memory_order) noexcept;
3860b57cec5SDimitry Andrictemplate<class T>
387349cc55cSDimitry Andric  void atomic_wait_explicit(const atomic<T>*, atomic<T>::value_type,
388bdd1243dSDimitry Andric                            memory_order) noexcept;
3890b57cec5SDimitry Andrictemplate<class T>
390bdd1243dSDimitry Andric  void atomic_notify_one(volatile atomic<T>*) noexcept;
3910b57cec5SDimitry Andrictemplate<class T>
392bdd1243dSDimitry Andric  void atomic_notify_one(atomic<T>*) noexcept;
3930b57cec5SDimitry Andrictemplate<class T>
394bdd1243dSDimitry Andric  void atomic_notify_all(volatile atomic<T>*) noexcept;
3950b57cec5SDimitry Andrictemplate<class T>
396bdd1243dSDimitry Andric  void atomic_notify_all(atomic<T>*) noexcept;
3970b57cec5SDimitry Andric
3980b57cec5SDimitry Andric// Atomics for standard typedef types
3990b57cec5SDimitry Andric
4000b57cec5SDimitry Andrictypedef atomic<bool>               atomic_bool;
4010b57cec5SDimitry Andrictypedef atomic<char>               atomic_char;
4020b57cec5SDimitry Andrictypedef atomic<signed char>        atomic_schar;
4030b57cec5SDimitry Andrictypedef atomic<unsigned char>      atomic_uchar;
4040b57cec5SDimitry Andrictypedef atomic<short>              atomic_short;
4050b57cec5SDimitry Andrictypedef atomic<unsigned short>     atomic_ushort;
4060b57cec5SDimitry Andrictypedef atomic<int>                atomic_int;
4070b57cec5SDimitry Andrictypedef atomic<unsigned int>       atomic_uint;
4080b57cec5SDimitry Andrictypedef atomic<long>               atomic_long;
4090b57cec5SDimitry Andrictypedef atomic<unsigned long>      atomic_ulong;
4100b57cec5SDimitry Andrictypedef atomic<long long>          atomic_llong;
4110b57cec5SDimitry Andrictypedef atomic<unsigned long long> atomic_ullong;
412e8d8bef9SDimitry Andrictypedef atomic<char8_t>            atomic_char8_t; // C++20
4130b57cec5SDimitry Andrictypedef atomic<char16_t>           atomic_char16_t;
4140b57cec5SDimitry Andrictypedef atomic<char32_t>           atomic_char32_t;
4150b57cec5SDimitry Andrictypedef atomic<wchar_t>            atomic_wchar_t;
4160b57cec5SDimitry Andric
4170b57cec5SDimitry Andrictypedef atomic<int_least8_t>   atomic_int_least8_t;
4180b57cec5SDimitry Andrictypedef atomic<uint_least8_t>  atomic_uint_least8_t;
4190b57cec5SDimitry Andrictypedef atomic<int_least16_t>  atomic_int_least16_t;
4200b57cec5SDimitry Andrictypedef atomic<uint_least16_t> atomic_uint_least16_t;
4210b57cec5SDimitry Andrictypedef atomic<int_least32_t>  atomic_int_least32_t;
4220b57cec5SDimitry Andrictypedef atomic<uint_least32_t> atomic_uint_least32_t;
4230b57cec5SDimitry Andrictypedef atomic<int_least64_t>  atomic_int_least64_t;
4240b57cec5SDimitry Andrictypedef atomic<uint_least64_t> atomic_uint_least64_t;
4250b57cec5SDimitry Andric
4260b57cec5SDimitry Andrictypedef atomic<int_fast8_t>   atomic_int_fast8_t;
4270b57cec5SDimitry Andrictypedef atomic<uint_fast8_t>  atomic_uint_fast8_t;
4280b57cec5SDimitry Andrictypedef atomic<int_fast16_t>  atomic_int_fast16_t;
4290b57cec5SDimitry Andrictypedef atomic<uint_fast16_t> atomic_uint_fast16_t;
4300b57cec5SDimitry Andrictypedef atomic<int_fast32_t>  atomic_int_fast32_t;
4310b57cec5SDimitry Andrictypedef atomic<uint_fast32_t> atomic_uint_fast32_t;
4320b57cec5SDimitry Andrictypedef atomic<int_fast64_t>  atomic_int_fast64_t;
4330b57cec5SDimitry Andrictypedef atomic<uint_fast64_t> atomic_uint_fast64_t;
4340b57cec5SDimitry Andric
4350b57cec5SDimitry Andrictypedef atomic<int8_t>   atomic_int8_t;
4360b57cec5SDimitry Andrictypedef atomic<uint8_t>  atomic_uint8_t;
4370b57cec5SDimitry Andrictypedef atomic<int16_t>  atomic_int16_t;
4380b57cec5SDimitry Andrictypedef atomic<uint16_t> atomic_uint16_t;
4390b57cec5SDimitry Andrictypedef atomic<int32_t>  atomic_int32_t;
4400b57cec5SDimitry Andrictypedef atomic<uint32_t> atomic_uint32_t;
4410b57cec5SDimitry Andrictypedef atomic<int64_t>  atomic_int64_t;
4420b57cec5SDimitry Andrictypedef atomic<uint64_t> atomic_uint64_t;
4430b57cec5SDimitry Andric
4440b57cec5SDimitry Andrictypedef atomic<intptr_t>  atomic_intptr_t;
4450b57cec5SDimitry Andrictypedef atomic<uintptr_t> atomic_uintptr_t;
4460b57cec5SDimitry Andrictypedef atomic<size_t>    atomic_size_t;
4470b57cec5SDimitry Andrictypedef atomic<ptrdiff_t> atomic_ptrdiff_t;
4480b57cec5SDimitry Andrictypedef atomic<intmax_t>  atomic_intmax_t;
4490b57cec5SDimitry Andrictypedef atomic<uintmax_t> atomic_uintmax_t;
4500b57cec5SDimitry Andric
4515ffd83dbSDimitry Andric// flag type and operations
4525ffd83dbSDimitry Andric
4535ffd83dbSDimitry Andrictypedef struct atomic_flag
4545ffd83dbSDimitry Andric{
455fe6060f1SDimitry Andric    atomic_flag() noexcept = default; // until C++20
456fe6060f1SDimitry Andric    constexpr atomic_flag() noexcept; // since C++20
4575ffd83dbSDimitry Andric    atomic_flag(const atomic_flag&) = delete;
4585ffd83dbSDimitry Andric    atomic_flag& operator=(const atomic_flag&) = delete;
4595ffd83dbSDimitry Andric    atomic_flag& operator=(const atomic_flag&) volatile = delete;
4605ffd83dbSDimitry Andric
4615ffd83dbSDimitry Andric    bool test(memory_order m = memory_order_seq_cst) volatile noexcept;
4625ffd83dbSDimitry Andric    bool test(memory_order m = memory_order_seq_cst) noexcept;
4635ffd83dbSDimitry Andric    bool test_and_set(memory_order m = memory_order_seq_cst) volatile noexcept;
4645ffd83dbSDimitry Andric    bool test_and_set(memory_order m = memory_order_seq_cst) noexcept;
4655ffd83dbSDimitry Andric    void clear(memory_order m = memory_order_seq_cst) volatile noexcept;
4665ffd83dbSDimitry Andric    void clear(memory_order m = memory_order_seq_cst) noexcept;
4675ffd83dbSDimitry Andric
4685ffd83dbSDimitry Andric    void wait(bool, memory_order = memory_order::seq_cst) const volatile noexcept;
4695ffd83dbSDimitry Andric    void wait(bool, memory_order = memory_order::seq_cst) const noexcept;
4705ffd83dbSDimitry Andric    void notify_one() volatile noexcept;
4715ffd83dbSDimitry Andric    void notify_one() noexcept;
4725ffd83dbSDimitry Andric    void notify_all() volatile noexcept;
4735ffd83dbSDimitry Andric    void notify_all() noexcept;
4745ffd83dbSDimitry Andric} atomic_flag;
4755ffd83dbSDimitry Andric
4765ffd83dbSDimitry Andricbool atomic_flag_test(volatile atomic_flag* obj) noexcept;
4775ffd83dbSDimitry Andricbool atomic_flag_test(atomic_flag* obj) noexcept;
4785ffd83dbSDimitry Andricbool atomic_flag_test_explicit(volatile atomic_flag* obj,
4795ffd83dbSDimitry Andric                               memory_order m) noexcept;
4805ffd83dbSDimitry Andricbool atomic_flag_test_explicit(atomic_flag* obj, memory_order m) noexcept;
4815ffd83dbSDimitry Andricbool atomic_flag_test_and_set(volatile atomic_flag* obj) noexcept;
4825ffd83dbSDimitry Andricbool atomic_flag_test_and_set(atomic_flag* obj) noexcept;
4835ffd83dbSDimitry Andricbool atomic_flag_test_and_set_explicit(volatile atomic_flag* obj,
4845ffd83dbSDimitry Andric                                       memory_order m) noexcept;
4855ffd83dbSDimitry Andricbool atomic_flag_test_and_set_explicit(atomic_flag* obj, memory_order m) noexcept;
4865ffd83dbSDimitry Andricvoid atomic_flag_clear(volatile atomic_flag* obj) noexcept;
4875ffd83dbSDimitry Andricvoid atomic_flag_clear(atomic_flag* obj) noexcept;
4885ffd83dbSDimitry Andricvoid atomic_flag_clear_explicit(volatile atomic_flag* obj, memory_order m) noexcept;
4895ffd83dbSDimitry Andricvoid atomic_flag_clear_explicit(atomic_flag* obj, memory_order m) noexcept;
4905ffd83dbSDimitry Andric
4915ffd83dbSDimitry Andricvoid atomic_wait(const volatile atomic_flag* obj, T old) noexcept;
4925ffd83dbSDimitry Andricvoid atomic_wait(const atomic_flag* obj, T old) noexcept;
4935ffd83dbSDimitry Andricvoid atomic_wait_explicit(const volatile atomic_flag* obj, T old, memory_order m) noexcept;
4945ffd83dbSDimitry Andricvoid atomic_wait_explicit(const atomic_flag* obj, T old, memory_order m) noexcept;
4955ffd83dbSDimitry Andricvoid atomic_one(volatile atomic_flag* obj) noexcept;
4965ffd83dbSDimitry Andricvoid atomic_one(atomic_flag* obj) noexcept;
4975ffd83dbSDimitry Andricvoid atomic_all(volatile atomic_flag* obj) noexcept;
4985ffd83dbSDimitry Andricvoid atomic_all(atomic_flag* obj) noexcept;
4995ffd83dbSDimitry Andric
5000b57cec5SDimitry Andric// fences
5010b57cec5SDimitry Andric
5020b57cec5SDimitry Andricvoid atomic_thread_fence(memory_order m) noexcept;
5030b57cec5SDimitry Andricvoid atomic_signal_fence(memory_order m) noexcept;
5040b57cec5SDimitry Andric
5055ffd83dbSDimitry Andric// deprecated
5065ffd83dbSDimitry Andric
5075ffd83dbSDimitry Andrictemplate <class T>
508349cc55cSDimitry Andric  void atomic_init(volatile atomic<T>* obj, atomic<T>::value_type desr) noexcept;
5095ffd83dbSDimitry Andric
5105ffd83dbSDimitry Andrictemplate <class T>
511349cc55cSDimitry Andric  void atomic_init(atomic<T>* obj, atomic<T>::value_type desr) noexcept;
5125ffd83dbSDimitry Andric
5135ffd83dbSDimitry Andric#define ATOMIC_VAR_INIT(value) see below
5145ffd83dbSDimitry Andric
5155ffd83dbSDimitry Andric#define ATOMIC_FLAG_INIT see below
5165ffd83dbSDimitry Andric
5170b57cec5SDimitry Andric}  // std
5180b57cec5SDimitry Andric
5190b57cec5SDimitry Andric*/
5200b57cec5SDimitry Andric
52181ad6265SDimitry Andric#include <__assert> // all public C++ headers provide the assertion handler
522*06c3fb27SDimitry Andric#include <__atomic/aliases.h>
523*06c3fb27SDimitry Andric#include <__atomic/atomic.h>
524*06c3fb27SDimitry Andric#include <__atomic/atomic_base.h>
525*06c3fb27SDimitry Andric#include <__atomic/atomic_flag.h>
526*06c3fb27SDimitry Andric#include <__atomic/atomic_init.h>
527*06c3fb27SDimitry Andric#include <__atomic/atomic_lock_free.h>
528*06c3fb27SDimitry Andric#include <__atomic/atomic_sync.h>
529*06c3fb27SDimitry Andric#include <__atomic/check_memory_order.h>
530*06c3fb27SDimitry Andric#include <__atomic/contention_t.h>
531*06c3fb27SDimitry Andric#include <__atomic/cxx_atomic_impl.h>
532*06c3fb27SDimitry Andric#include <__atomic/fence.h>
533*06c3fb27SDimitry Andric#include <__atomic/is_always_lock_free.h>
534*06c3fb27SDimitry Andric#include <__atomic/kill_dependency.h>
535*06c3fb27SDimitry Andric#include <__atomic/memory_order.h>
536fe6060f1SDimitry Andric#include <__config>
5370b57cec5SDimitry Andric#include <version>
5380b57cec5SDimitry Andric
5390b57cec5SDimitry Andric#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
5400b57cec5SDimitry Andric#  pragma GCC system_header
5410b57cec5SDimitry Andric#endif
5420b57cec5SDimitry Andric
5430b57cec5SDimitry Andric#ifdef _LIBCPP_HAS_NO_ATOMIC_HEADER
5440b57cec5SDimitry Andric#  error <atomic> is not implemented
5450b57cec5SDimitry Andric#endif
546*06c3fb27SDimitry Andric
5470b57cec5SDimitry Andric#ifdef kill_dependency
54881ad6265SDimitry Andric#  error <atomic> is incompatible with <stdatomic.h> before C++23. Please compile with -std=c++23.
5490b57cec5SDimitry Andric#endif
5500b57cec5SDimitry Andric
551bdd1243dSDimitry Andric#if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20
552bdd1243dSDimitry Andric#  include <cmath>
553bdd1243dSDimitry Andric#  include <compare>
554*06c3fb27SDimitry Andric#  include <cstring>
555bdd1243dSDimitry Andric#  include <type_traits>
556bdd1243dSDimitry Andric#endif
557bdd1243dSDimitry Andric
5580b57cec5SDimitry Andric#endif // _LIBCPP_ATOMIC
559