// -*- C++ -*- //===----------------------------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// #ifndef _LIBCPP_ATOMIC #define _LIBCPP_ATOMIC /* atomic synopsis namespace std { // feature test macro [version.syn] #define __cpp_lib_atomic_is_always_lock_free #define __cpp_lib_atomic_flag_test #define __cpp_lib_atomic_lock_free_type_aliases #define __cpp_lib_atomic_wait // order and consistency enum memory_order: unspecified // enum class in C++20 { relaxed, consume, // load-consume acquire, // load-acquire release, // store-release acq_rel, // store-release load-acquire seq_cst // store-release load-acquire }; inline constexpr auto memory_order_relaxed = memory_order::relaxed; inline constexpr auto memory_order_consume = memory_order::consume; inline constexpr auto memory_order_acquire = memory_order::acquire; inline constexpr auto memory_order_release = memory_order::release; inline constexpr auto memory_order_acq_rel = memory_order::acq_rel; inline constexpr auto memory_order_seq_cst = memory_order::seq_cst; template T kill_dependency(T y) noexcept; // lock-free property #define ATOMIC_BOOL_LOCK_FREE unspecified #define ATOMIC_CHAR_LOCK_FREE unspecified #define ATOMIC_CHAR8_T_LOCK_FREE unspecified // C++20 #define ATOMIC_CHAR16_T_LOCK_FREE unspecified #define ATOMIC_CHAR32_T_LOCK_FREE unspecified #define ATOMIC_WCHAR_T_LOCK_FREE unspecified #define ATOMIC_SHORT_LOCK_FREE unspecified #define ATOMIC_INT_LOCK_FREE unspecified #define ATOMIC_LONG_LOCK_FREE unspecified #define ATOMIC_LLONG_LOCK_FREE unspecified #define ATOMIC_POINTER_LOCK_FREE unspecified template struct atomic { using value_type = T; static constexpr bool is_always_lock_free; bool is_lock_free() const volatile noexcept; bool is_lock_free() const noexcept; atomic() noexcept = default; // until C++20 constexpr atomic() noexcept(is_nothrow_default_constructible_v); // since C++20 constexpr atomic(T desr) noexcept; atomic(const atomic&) = delete; atomic& operator=(const atomic&) = delete; atomic& operator=(const atomic&) volatile = delete; T load(memory_order m = memory_order_seq_cst) const volatile noexcept; T load(memory_order m = memory_order_seq_cst) const noexcept; operator T() const volatile noexcept; operator T() const noexcept; void store(T desr, memory_order m = memory_order_seq_cst) volatile noexcept; void store(T desr, memory_order m = memory_order_seq_cst) noexcept; T operator=(T) volatile noexcept; T operator=(T) noexcept; T exchange(T desr, memory_order m = memory_order_seq_cst) volatile noexcept; T exchange(T desr, memory_order m = memory_order_seq_cst) noexcept; bool compare_exchange_weak(T& expc, T desr, memory_order s, memory_order f) volatile noexcept; bool compare_exchange_weak(T& expc, T desr, memory_order s, memory_order f) noexcept; bool compare_exchange_strong(T& expc, T desr, memory_order s, memory_order f) volatile noexcept; bool compare_exchange_strong(T& expc, T desr, memory_order s, memory_order f) noexcept; bool compare_exchange_weak(T& expc, T desr, memory_order m = memory_order_seq_cst) volatile noexcept; bool compare_exchange_weak(T& expc, T desr, memory_order m = memory_order_seq_cst) noexcept; bool compare_exchange_strong(T& expc, T desr, memory_order m = memory_order_seq_cst) volatile noexcept; bool compare_exchange_strong(T& expc, T desr, memory_order m = memory_order_seq_cst) noexcept; void wait(T, memory_order = memory_order::seq_cst) const volatile noexcept; void wait(T, memory_order = memory_order::seq_cst) const noexcept; void notify_one() volatile noexcept; void notify_one() noexcept; void notify_all() volatile noexcept; void notify_all() noexcept; }; template <> struct atomic { using value_type = integral; using difference_type = value_type; static constexpr bool is_always_lock_free; bool is_lock_free() const volatile noexcept; bool is_lock_free() const noexcept; atomic() noexcept = default; constexpr atomic(integral desr) noexcept; atomic(const atomic&) = delete; atomic& operator=(const atomic&) = delete; atomic& operator=(const atomic&) volatile = delete; integral load(memory_order m = memory_order_seq_cst) const volatile noexcept; integral load(memory_order m = memory_order_seq_cst) const noexcept; operator integral() const volatile noexcept; operator integral() const noexcept; void store(integral desr, memory_order m = memory_order_seq_cst) volatile noexcept; void store(integral desr, memory_order m = memory_order_seq_cst) noexcept; integral operator=(integral desr) volatile noexcept; integral operator=(integral desr) noexcept; integral exchange(integral desr, memory_order m = memory_order_seq_cst) volatile noexcept; integral exchange(integral desr, memory_order m = memory_order_seq_cst) noexcept; bool compare_exchange_weak(integral& expc, integral desr, memory_order s, memory_order f) volatile noexcept; bool compare_exchange_weak(integral& expc, integral desr, memory_order s, memory_order f) noexcept; bool compare_exchange_strong(integral& expc, integral desr, memory_order s, memory_order f) volatile noexcept; bool compare_exchange_strong(integral& expc, integral desr, memory_order s, memory_order f) noexcept; bool compare_exchange_weak(integral& expc, integral desr, memory_order m = memory_order_seq_cst) volatile noexcept; bool compare_exchange_weak(integral& expc, integral desr, memory_order m = memory_order_seq_cst) noexcept; bool compare_exchange_strong(integral& expc, integral desr, memory_order m = memory_order_seq_cst) volatile noexcept; bool compare_exchange_strong(integral& expc, integral desr, memory_order m = memory_order_seq_cst) noexcept; integral fetch_add(integral op, memory_order m = memory_order_seq_cst) volatile noexcept; integral fetch_add(integral op, memory_order m = memory_order_seq_cst) noexcept; integral fetch_sub(integral op, memory_order m = memory_order_seq_cst) volatile noexcept; integral fetch_sub(integral op, memory_order m = memory_order_seq_cst) noexcept; integral fetch_and(integral op, memory_order m = memory_order_seq_cst) volatile noexcept; integral fetch_and(integral op, memory_order m = memory_order_seq_cst) noexcept; integral fetch_or(integral op, memory_order m = memory_order_seq_cst) volatile noexcept; integral fetch_or(integral op, memory_order m = memory_order_seq_cst) noexcept; integral fetch_xor(integral op, memory_order m = memory_order_seq_cst) volatile noexcept; integral fetch_xor(integral op, memory_order m = memory_order_seq_cst) noexcept; integral operator++(int) volatile noexcept; integral operator++(int) noexcept; integral operator--(int) volatile noexcept; integral operator--(int) noexcept; integral operator++() volatile noexcept; integral operator++() noexcept; integral operator--() volatile noexcept; integral operator--() noexcept; integral operator+=(integral op) volatile noexcept; integral operator+=(integral op) noexcept; integral operator-=(integral op) volatile noexcept; integral operator-=(integral op) noexcept; integral operator&=(integral op) volatile noexcept; integral operator&=(integral op) noexcept; integral operator|=(integral op) volatile noexcept; integral operator|=(integral op) noexcept; integral operator^=(integral op) volatile noexcept; integral operator^=(integral op) noexcept; void wait(integral, memory_order = memory_order::seq_cst) const volatile noexcept; void wait(integral, memory_order = memory_order::seq_cst) const noexcept; void notify_one() volatile noexcept; void notify_one() noexcept; void notify_all() volatile noexcept; void notify_all() noexcept; }; template struct atomic { using value_type = T*; using difference_type = ptrdiff_t; static constexpr bool is_always_lock_free; bool is_lock_free() const volatile noexcept; bool is_lock_free() const noexcept; atomic() noexcept = default; // until C++20 constexpr atomic() noexcept; // since C++20 constexpr atomic(T* desr) noexcept; atomic(const atomic&) = delete; atomic& operator=(const atomic&) = delete; atomic& operator=(const atomic&) volatile = delete; T* load(memory_order m = memory_order_seq_cst) const volatile noexcept; T* load(memory_order m = memory_order_seq_cst) const noexcept; operator T*() const volatile noexcept; operator T*() const noexcept; void store(T* desr, memory_order m = memory_order_seq_cst) volatile noexcept; void store(T* desr, memory_order m = memory_order_seq_cst) noexcept; T* operator=(T*) volatile noexcept; T* operator=(T*) noexcept; T* exchange(T* desr, memory_order m = memory_order_seq_cst) volatile noexcept; T* exchange(T* desr, memory_order m = memory_order_seq_cst) noexcept; bool compare_exchange_weak(T*& expc, T* desr, memory_order s, memory_order f) volatile noexcept; bool compare_exchange_weak(T*& expc, T* desr, memory_order s, memory_order f) noexcept; bool compare_exchange_strong(T*& expc, T* desr, memory_order s, memory_order f) volatile noexcept; bool compare_exchange_strong(T*& expc, T* desr, memory_order s, memory_order f) noexcept; bool compare_exchange_weak(T*& expc, T* desr, memory_order m = memory_order_seq_cst) volatile noexcept; bool compare_exchange_weak(T*& expc, T* desr, memory_order m = memory_order_seq_cst) noexcept; bool compare_exchange_strong(T*& expc, T* desr, memory_order m = memory_order_seq_cst) volatile noexcept; bool compare_exchange_strong(T*& expc, T* desr, memory_order m = memory_order_seq_cst) noexcept; T* fetch_add(ptrdiff_t op, memory_order m = memory_order_seq_cst) volatile noexcept; T* fetch_add(ptrdiff_t op, memory_order m = memory_order_seq_cst) noexcept; T* fetch_sub(ptrdiff_t op, memory_order m = memory_order_seq_cst) volatile noexcept; T* fetch_sub(ptrdiff_t op, memory_order m = memory_order_seq_cst) noexcept; T* operator++(int) volatile noexcept; T* operator++(int) noexcept; T* operator--(int) volatile noexcept; T* operator--(int) noexcept; T* operator++() volatile noexcept; T* operator++() noexcept; T* operator--() volatile noexcept; T* operator--() noexcept; T* operator+=(ptrdiff_t op) volatile noexcept; T* operator+=(ptrdiff_t op) noexcept; T* operator-=(ptrdiff_t op) volatile noexcept; T* operator-=(ptrdiff_t op) noexcept; void wait(T*, memory_order = memory_order::seq_cst) const volatile noexcept; void wait(T*, memory_order = memory_order::seq_cst) const noexcept; void notify_one() volatile noexcept; void notify_one() noexcept; void notify_all() volatile noexcept; void notify_all() noexcept; }; // [atomics.nonmembers], non-member functions template bool atomic_is_lock_free(const volatile atomic*) noexcept; template bool atomic_is_lock_free(const atomic*) noexcept; template void atomic_store(volatile atomic*, atomic::value_type) noexcept; template void atomic_store(atomic*, atomic::value_type) noexcept; template void atomic_store_explicit(volatile atomic*, atomic::value_type, memory_order) noexcept; template void atomic_store_explicit(atomic*, atomic::value_type, memory_order) noexcept; template T atomic_load(const volatile atomic*) noexcept; template T atomic_load(const atomic*) noexcept; template T atomic_load_explicit(const volatile atomic*, memory_order) noexcept; template T atomic_load_explicit(const atomic*, memory_order) noexcept; template T atomic_exchange(volatile atomic*, atomic::value_type) noexcept; template T atomic_exchange(atomic*, atomic::value_type) noexcept; template T atomic_exchange_explicit(volatile atomic*, atomic::value_type, memory_order) noexcept; template T atomic_exchange_explicit(atomic*, atomic::value_type, memory_order) noexcept; template bool atomic_compare_exchange_weak(volatile atomic*, atomic::value_type*, atomic::value_type) noexcept; template bool atomic_compare_exchange_weak(atomic*, atomic::value_type*, atomic::value_type) noexcept; template bool atomic_compare_exchange_strong(volatile atomic*, atomic::value_type*, atomic::value_type) noexcept; template bool atomic_compare_exchange_strong(atomic*, atomic::value_type*, atomic::value_type) noexcept; template bool atomic_compare_exchange_weak_explicit(volatile atomic*, atomic::value_type*, atomic::value_type, memory_order, memory_order) noexcept; template bool atomic_compare_exchange_weak_explicit(atomic*, atomic::value_type*, atomic::value_type, memory_order, memory_order) noexcept; template bool atomic_compare_exchange_strong_explicit(volatile atomic*, atomic::value_type*, atomic::value_type, memory_order, memory_order) noexcept; template bool atomic_compare_exchange_strong_explicit(atomic*, atomic::value_type*, atomic::value_type, memory_order, memory_order) noexcept; template T atomic_fetch_add(volatile atomic*, atomic::difference_type) noexcept; template T atomic_fetch_add(atomic*, atomic::difference_type) noexcept; template T atomic_fetch_add_explicit(volatile atomic*, atomic::difference_type, memory_order) noexcept; template T atomic_fetch_add_explicit(atomic*, atomic::difference_type, memory_order) noexcept; template T atomic_fetch_sub(volatile atomic*, atomic::difference_type) noexcept; template T atomic_fetch_sub(atomic*, atomic::difference_type) noexcept; template T atomic_fetch_sub_explicit(volatile atomic*, atomic::difference_type, memory_order) noexcept; template T atomic_fetch_sub_explicit(atomic*, atomic::difference_type, memory_order) noexcept; template T atomic_fetch_and(volatile atomic*, atomic::value_type) noexcept; template T atomic_fetch_and(atomic*, atomic::value_type) noexcept; template T atomic_fetch_and_explicit(volatile atomic*, atomic::value_type, memory_order) noexcept; template T atomic_fetch_and_explicit(atomic*, atomic::value_type, memory_order) noexcept; template T atomic_fetch_or(volatile atomic*, atomic::value_type) noexcept; template T atomic_fetch_or(atomic*, atomic::value_type) noexcept; template T atomic_fetch_or_explicit(volatile atomic*, atomic::value_type, memory_order) noexcept; template T atomic_fetch_or_explicit(atomic*, atomic::value_type, memory_order) noexcept; template T atomic_fetch_xor(volatile atomic*, atomic::value_type) noexcept; template T atomic_fetch_xor(atomic*, atomic::value_type) noexcept; template T atomic_fetch_xor_explicit(volatile atomic*, atomic::value_type, memory_order) noexcept; template T atomic_fetch_xor_explicit(atomic*, atomic::value_type, memory_order) noexcept; template void atomic_wait(const volatile atomic*, atomic::value_type); template void atomic_wait(const atomic*, atomic::value_type); template void atomic_wait_explicit(const volatile atomic*, atomic::value_type, memory_order); template void atomic_wait_explicit(const atomic*, atomic::value_type, memory_order); template void atomic_notify_one(volatile atomic*); template void atomic_notify_one(atomic*); template void atomic_notify_all(volatile atomic*); template void atomic_notify_all(atomic*); // Atomics for standard typedef types typedef atomic atomic_bool; typedef atomic atomic_char; typedef atomic atomic_schar; typedef atomic atomic_uchar; typedef atomic atomic_short; typedef atomic atomic_ushort; typedef atomic atomic_int; typedef atomic atomic_uint; typedef atomic atomic_long; typedef atomic atomic_ulong; typedef atomic atomic_llong; typedef atomic atomic_ullong; typedef atomic atomic_char8_t; // C++20 typedef atomic atomic_char16_t; typedef atomic atomic_char32_t; typedef atomic atomic_wchar_t; typedef atomic atomic_int_least8_t; typedef atomic atomic_uint_least8_t; typedef atomic atomic_int_least16_t; typedef atomic atomic_uint_least16_t; typedef atomic atomic_int_least32_t; typedef atomic atomic_uint_least32_t; typedef atomic atomic_int_least64_t; typedef atomic atomic_uint_least64_t; typedef atomic atomic_int_fast8_t; typedef atomic atomic_uint_fast8_t; typedef atomic atomic_int_fast16_t; typedef atomic atomic_uint_fast16_t; typedef atomic atomic_int_fast32_t; typedef atomic atomic_uint_fast32_t; typedef atomic atomic_int_fast64_t; typedef atomic atomic_uint_fast64_t; typedef atomic atomic_int8_t; typedef atomic atomic_uint8_t; typedef atomic atomic_int16_t; typedef atomic atomic_uint16_t; typedef atomic atomic_int32_t; typedef atomic atomic_uint32_t; typedef atomic atomic_int64_t; typedef atomic atomic_uint64_t; typedef atomic atomic_intptr_t; typedef atomic atomic_uintptr_t; typedef atomic atomic_size_t; typedef atomic atomic_ptrdiff_t; typedef atomic atomic_intmax_t; typedef atomic atomic_uintmax_t; // flag type and operations typedef struct atomic_flag { atomic_flag() noexcept = default; // until C++20 constexpr atomic_flag() noexcept; // since C++20 atomic_flag(const atomic_flag&) = delete; atomic_flag& operator=(const atomic_flag&) = delete; atomic_flag& operator=(const atomic_flag&) volatile = delete; bool test(memory_order m = memory_order_seq_cst) volatile noexcept; bool test(memory_order m = memory_order_seq_cst) noexcept; bool test_and_set(memory_order m = memory_order_seq_cst) volatile noexcept; bool test_and_set(memory_order m = memory_order_seq_cst) noexcept; void clear(memory_order m = memory_order_seq_cst) volatile noexcept; void clear(memory_order m = memory_order_seq_cst) noexcept; void wait(bool, memory_order = memory_order::seq_cst) const volatile noexcept; void wait(bool, memory_order = memory_order::seq_cst) const noexcept; void notify_one() volatile noexcept; void notify_one() noexcept; void notify_all() volatile noexcept; void notify_all() noexcept; } atomic_flag; bool atomic_flag_test(volatile atomic_flag* obj) noexcept; bool atomic_flag_test(atomic_flag* obj) noexcept; bool atomic_flag_test_explicit(volatile atomic_flag* obj, memory_order m) noexcept; bool atomic_flag_test_explicit(atomic_flag* obj, memory_order m) noexcept; bool atomic_flag_test_and_set(volatile atomic_flag* obj) noexcept; bool atomic_flag_test_and_set(atomic_flag* obj) noexcept; bool atomic_flag_test_and_set_explicit(volatile atomic_flag* obj, memory_order m) noexcept; bool atomic_flag_test_and_set_explicit(atomic_flag* obj, memory_order m) noexcept; void atomic_flag_clear(volatile atomic_flag* obj) noexcept; void atomic_flag_clear(atomic_flag* obj) noexcept; void atomic_flag_clear_explicit(volatile atomic_flag* obj, memory_order m) noexcept; void atomic_flag_clear_explicit(atomic_flag* obj, memory_order m) noexcept; void atomic_wait(const volatile atomic_flag* obj, T old) noexcept; void atomic_wait(const atomic_flag* obj, T old) noexcept; void atomic_wait_explicit(const volatile atomic_flag* obj, T old, memory_order m) noexcept; void atomic_wait_explicit(const atomic_flag* obj, T old, memory_order m) noexcept; void atomic_one(volatile atomic_flag* obj) noexcept; void atomic_one(atomic_flag* obj) noexcept; void atomic_all(volatile atomic_flag* obj) noexcept; void atomic_all(atomic_flag* obj) noexcept; // fences void atomic_thread_fence(memory_order m) noexcept; void atomic_signal_fence(memory_order m) noexcept; // deprecated template void atomic_init(volatile atomic* obj, atomic::value_type desr) noexcept; template void atomic_init(atomic* obj, atomic::value_type desr) noexcept; #define ATOMIC_VAR_INIT(value) see below #define ATOMIC_FLAG_INIT see below } // std */ #include <__assert> // all public C++ headers provide the assertion handler #include <__availability> #include <__chrono/duration.h> #include <__config> #include <__thread/poll_with_backoff.h> #include <__thread/timed_backoff_policy.h> #include #include #include #include #include #ifndef _LIBCPP_HAS_NO_THREADS # include <__threading_support> #endif #ifndef _LIBCPP_REMOVE_TRANSITIVE_INCLUDES # include #endif #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header #endif #ifdef _LIBCPP_HAS_NO_ATOMIC_HEADER # error is not implemented #endif #ifdef kill_dependency # error is incompatible with before C++23. Please compile with -std=c++23. #endif #define _LIBCPP_CHECK_STORE_MEMORY_ORDER(__m) \ _LIBCPP_DIAGNOSE_WARNING(__m == memory_order_consume || \ __m == memory_order_acquire || \ __m == memory_order_acq_rel, \ "memory order argument to atomic operation is invalid") #define _LIBCPP_CHECK_LOAD_MEMORY_ORDER(__m) \ _LIBCPP_DIAGNOSE_WARNING(__m == memory_order_release || \ __m == memory_order_acq_rel, \ "memory order argument to atomic operation is invalid") #define _LIBCPP_CHECK_EXCHANGE_MEMORY_ORDER(__m, __f) \ _LIBCPP_DIAGNOSE_WARNING(__f == memory_order_release || \ __f == memory_order_acq_rel, \ "memory order argument to atomic operation is invalid") _LIBCPP_BEGIN_NAMESPACE_STD // Figure out what the underlying type for `memory_order` would be if it were // declared as an unscoped enum (accounting for -fshort-enums). Use this result // to pin the underlying type in C++20. enum __legacy_memory_order { __mo_relaxed, __mo_consume, __mo_acquire, __mo_release, __mo_acq_rel, __mo_seq_cst }; typedef underlying_type<__legacy_memory_order>::type __memory_order_underlying_t; #if _LIBCPP_STD_VER > 17 enum class memory_order : __memory_order_underlying_t { relaxed = __mo_relaxed, consume = __mo_consume, acquire = __mo_acquire, release = __mo_release, acq_rel = __mo_acq_rel, seq_cst = __mo_seq_cst }; inline constexpr auto memory_order_relaxed = memory_order::relaxed; inline constexpr auto memory_order_consume = memory_order::consume; inline constexpr auto memory_order_acquire = memory_order::acquire; inline constexpr auto memory_order_release = memory_order::release; inline constexpr auto memory_order_acq_rel = memory_order::acq_rel; inline constexpr auto memory_order_seq_cst = memory_order::seq_cst; #else typedef enum memory_order { memory_order_relaxed = __mo_relaxed, memory_order_consume = __mo_consume, memory_order_acquire = __mo_acquire, memory_order_release = __mo_release, memory_order_acq_rel = __mo_acq_rel, memory_order_seq_cst = __mo_seq_cst, } memory_order; #endif // _LIBCPP_STD_VER > 17 template _LIBCPP_INLINE_VISIBILITY bool __cxx_nonatomic_compare_equal(_Tp const& __lhs, _Tp const& __rhs) { return _VSTD::memcmp(&__lhs, &__rhs, sizeof(_Tp)) == 0; } static_assert((is_same::type, __memory_order_underlying_t>::value), "unexpected underlying type for std::memory_order"); #if defined(_LIBCPP_HAS_GCC_ATOMIC_IMP) || \ defined(_LIBCPP_ATOMIC_ONLY_USE_BUILTINS) // [atomics.types.generic]p1 guarantees _Tp is trivially copyable. Because // the default operator= in an object is not volatile, a byte-by-byte copy // is required. template _LIBCPP_INLINE_VISIBILITY typename enable_if::value>::type __cxx_atomic_assign_volatile(_Tp& __a_value, _Tv const& __val) { __a_value = __val; } template _LIBCPP_INLINE_VISIBILITY typename enable_if::value>::type __cxx_atomic_assign_volatile(_Tp volatile& __a_value, _Tv volatile const& __val) { volatile char* __to = reinterpret_cast(&__a_value); volatile char* __end = __to + sizeof(_Tp); volatile const char* __from = reinterpret_cast(&__val); while (__to != __end) *__to++ = *__from++; } #endif #if defined(_LIBCPP_HAS_GCC_ATOMIC_IMP) template struct __cxx_atomic_base_impl { _LIBCPP_INLINE_VISIBILITY #ifndef _LIBCPP_CXX03_LANG __cxx_atomic_base_impl() _NOEXCEPT = default; #else __cxx_atomic_base_impl() _NOEXCEPT : __a_value() {} #endif // _LIBCPP_CXX03_LANG _LIBCPP_CONSTEXPR explicit __cxx_atomic_base_impl(_Tp value) _NOEXCEPT : __a_value(value) {} _Tp __a_value; }; _LIBCPP_INLINE_VISIBILITY inline _LIBCPP_CONSTEXPR int __to_gcc_order(memory_order __order) { // Avoid switch statement to make this a constexpr. return __order == memory_order_relaxed ? __ATOMIC_RELAXED: (__order == memory_order_acquire ? __ATOMIC_ACQUIRE: (__order == memory_order_release ? __ATOMIC_RELEASE: (__order == memory_order_seq_cst ? __ATOMIC_SEQ_CST: (__order == memory_order_acq_rel ? __ATOMIC_ACQ_REL: __ATOMIC_CONSUME)))); } _LIBCPP_INLINE_VISIBILITY inline _LIBCPP_CONSTEXPR int __to_gcc_failure_order(memory_order __order) { // Avoid switch statement to make this a constexpr. return __order == memory_order_relaxed ? __ATOMIC_RELAXED: (__order == memory_order_acquire ? __ATOMIC_ACQUIRE: (__order == memory_order_release ? __ATOMIC_RELAXED: (__order == memory_order_seq_cst ? __ATOMIC_SEQ_CST: (__order == memory_order_acq_rel ? __ATOMIC_ACQUIRE: __ATOMIC_CONSUME)))); } template _LIBCPP_INLINE_VISIBILITY void __cxx_atomic_init(volatile __cxx_atomic_base_impl<_Tp>* __a, _Tp __val) { __cxx_atomic_assign_volatile(__a->__a_value, __val); } template _LIBCPP_INLINE_VISIBILITY void __cxx_atomic_init(__cxx_atomic_base_impl<_Tp>* __a, _Tp __val) { __a->__a_value = __val; } _LIBCPP_INLINE_VISIBILITY inline void __cxx_atomic_thread_fence(memory_order __order) { __atomic_thread_fence(__to_gcc_order(__order)); } _LIBCPP_INLINE_VISIBILITY inline void __cxx_atomic_signal_fence(memory_order __order) { __atomic_signal_fence(__to_gcc_order(__order)); } template _LIBCPP_INLINE_VISIBILITY void __cxx_atomic_store(volatile __cxx_atomic_base_impl<_Tp>* __a, _Tp __val, memory_order __order) { __atomic_store(&__a->__a_value, &__val, __to_gcc_order(__order)); } template _LIBCPP_INLINE_VISIBILITY void __cxx_atomic_store(__cxx_atomic_base_impl<_Tp>* __a, _Tp __val, memory_order __order) { __atomic_store(&__a->__a_value, &__val, __to_gcc_order(__order)); } template _LIBCPP_INLINE_VISIBILITY _Tp __cxx_atomic_load(const volatile __cxx_atomic_base_impl<_Tp>* __a, memory_order __order) { _Tp __ret; __atomic_load(&__a->__a_value, &__ret, __to_gcc_order(__order)); return __ret; } template _LIBCPP_INLINE_VISIBILITY _Tp __cxx_atomic_load(const __cxx_atomic_base_impl<_Tp>* __a, memory_order __order) { _Tp __ret; __atomic_load(&__a->__a_value, &__ret, __to_gcc_order(__order)); return __ret; } template _LIBCPP_INLINE_VISIBILITY _Tp __cxx_atomic_exchange(volatile __cxx_atomic_base_impl<_Tp>* __a, _Tp __value, memory_order __order) { _Tp __ret; __atomic_exchange(&__a->__a_value, &__value, &__ret, __to_gcc_order(__order)); return __ret; } template _LIBCPP_INLINE_VISIBILITY _Tp __cxx_atomic_exchange(__cxx_atomic_base_impl<_Tp>* __a, _Tp __value, memory_order __order) { _Tp __ret; __atomic_exchange(&__a->__a_value, &__value, &__ret, __to_gcc_order(__order)); return __ret; } template _LIBCPP_INLINE_VISIBILITY bool __cxx_atomic_compare_exchange_strong( volatile __cxx_atomic_base_impl<_Tp>* __a, _Tp* __expected, _Tp __value, memory_order __success, memory_order __failure) { return __atomic_compare_exchange(&__a->__a_value, __expected, &__value, false, __to_gcc_order(__success), __to_gcc_failure_order(__failure)); } template _LIBCPP_INLINE_VISIBILITY bool __cxx_atomic_compare_exchange_strong( __cxx_atomic_base_impl<_Tp>* __a, _Tp* __expected, _Tp __value, memory_order __success, memory_order __failure) { return __atomic_compare_exchange(&__a->__a_value, __expected, &__value, false, __to_gcc_order(__success), __to_gcc_failure_order(__failure)); } template _LIBCPP_INLINE_VISIBILITY bool __cxx_atomic_compare_exchange_weak( volatile __cxx_atomic_base_impl<_Tp>* __a, _Tp* __expected, _Tp __value, memory_order __success, memory_order __failure) { return __atomic_compare_exchange(&__a->__a_value, __expected, &__value, true, __to_gcc_order(__success), __to_gcc_failure_order(__failure)); } template _LIBCPP_INLINE_VISIBILITY bool __cxx_atomic_compare_exchange_weak( __cxx_atomic_base_impl<_Tp>* __a, _Tp* __expected, _Tp __value, memory_order __success, memory_order __failure) { return __atomic_compare_exchange(&__a->__a_value, __expected, &__value, true, __to_gcc_order(__success), __to_gcc_failure_order(__failure)); } template struct __skip_amt { enum {value = 1}; }; template struct __skip_amt<_Tp*> { enum {value = sizeof(_Tp)}; }; // FIXME: Haven't figured out what the spec says about using arrays with // atomic_fetch_add. Force a failure rather than creating bad behavior. template struct __skip_amt<_Tp[]> { }; template struct __skip_amt<_Tp[n]> { }; template _LIBCPP_INLINE_VISIBILITY _Tp __cxx_atomic_fetch_add(volatile __cxx_atomic_base_impl<_Tp>* __a, _Td __delta, memory_order __order) { return __atomic_fetch_add(&__a->__a_value, __delta * __skip_amt<_Tp>::value, __to_gcc_order(__order)); } template _LIBCPP_INLINE_VISIBILITY _Tp __cxx_atomic_fetch_add(__cxx_atomic_base_impl<_Tp>* __a, _Td __delta, memory_order __order) { return __atomic_fetch_add(&__a->__a_value, __delta * __skip_amt<_Tp>::value, __to_gcc_order(__order)); } template _LIBCPP_INLINE_VISIBILITY _Tp __cxx_atomic_fetch_sub(volatile __cxx_atomic_base_impl<_Tp>* __a, _Td __delta, memory_order __order) { return __atomic_fetch_sub(&__a->__a_value, __delta * __skip_amt<_Tp>::value, __to_gcc_order(__order)); } template _LIBCPP_INLINE_VISIBILITY _Tp __cxx_atomic_fetch_sub(__cxx_atomic_base_impl<_Tp>* __a, _Td __delta, memory_order __order) { return __atomic_fetch_sub(&__a->__a_value, __delta * __skip_amt<_Tp>::value, __to_gcc_order(__order)); } template _LIBCPP_INLINE_VISIBILITY _Tp __cxx_atomic_fetch_and(volatile __cxx_atomic_base_impl<_Tp>* __a, _Tp __pattern, memory_order __order) { return __atomic_fetch_and(&__a->__a_value, __pattern, __to_gcc_order(__order)); } template _LIBCPP_INLINE_VISIBILITY _Tp __cxx_atomic_fetch_and(__cxx_atomic_base_impl<_Tp>* __a, _Tp __pattern, memory_order __order) { return __atomic_fetch_and(&__a->__a_value, __pattern, __to_gcc_order(__order)); } template _LIBCPP_INLINE_VISIBILITY _Tp __cxx_atomic_fetch_or(volatile __cxx_atomic_base_impl<_Tp>* __a, _Tp __pattern, memory_order __order) { return __atomic_fetch_or(&__a->__a_value, __pattern, __to_gcc_order(__order)); } template _LIBCPP_INLINE_VISIBILITY _Tp __cxx_atomic_fetch_or(__cxx_atomic_base_impl<_Tp>* __a, _Tp __pattern, memory_order __order) { return __atomic_fetch_or(&__a->__a_value, __pattern, __to_gcc_order(__order)); } template _LIBCPP_INLINE_VISIBILITY _Tp __cxx_atomic_fetch_xor(volatile __cxx_atomic_base_impl<_Tp>* __a, _Tp __pattern, memory_order __order) { return __atomic_fetch_xor(&__a->__a_value, __pattern, __to_gcc_order(__order)); } template _LIBCPP_INLINE_VISIBILITY _Tp __cxx_atomic_fetch_xor(__cxx_atomic_base_impl<_Tp>* __a, _Tp __pattern, memory_order __order) { return __atomic_fetch_xor(&__a->__a_value, __pattern, __to_gcc_order(__order)); } #define __cxx_atomic_is_lock_free(__s) __atomic_is_lock_free(__s, 0) #elif defined(_LIBCPP_HAS_C_ATOMIC_IMP) template struct __cxx_atomic_base_impl { _LIBCPP_INLINE_VISIBILITY #ifndef _LIBCPP_CXX03_LANG __cxx_atomic_base_impl() _NOEXCEPT = default; #else __cxx_atomic_base_impl() _NOEXCEPT : __a_value() {} #endif // _LIBCPP_CXX03_LANG _LIBCPP_CONSTEXPR explicit __cxx_atomic_base_impl(_Tp __value) _NOEXCEPT : __a_value(__value) {} _LIBCPP_DISABLE_EXTENSION_WARNING _Atomic(_Tp) __a_value; }; #define __cxx_atomic_is_lock_free(__s) __c11_atomic_is_lock_free(__s) _LIBCPP_INLINE_VISIBILITY inline void __cxx_atomic_thread_fence(memory_order __order) _NOEXCEPT { __c11_atomic_thread_fence(static_cast<__memory_order_underlying_t>(__order)); } _LIBCPP_INLINE_VISIBILITY inline void __cxx_atomic_signal_fence(memory_order __order) _NOEXCEPT { __c11_atomic_signal_fence(static_cast<__memory_order_underlying_t>(__order)); } template _LIBCPP_INLINE_VISIBILITY void __cxx_atomic_init(__cxx_atomic_base_impl<_Tp> volatile* __a, _Tp __val) _NOEXCEPT { __c11_atomic_init(&__a->__a_value, __val); } template _LIBCPP_INLINE_VISIBILITY void __cxx_atomic_init(__cxx_atomic_base_impl<_Tp> * __a, _Tp __val) _NOEXCEPT { __c11_atomic_init(&__a->__a_value, __val); } template _LIBCPP_INLINE_VISIBILITY void __cxx_atomic_store(__cxx_atomic_base_impl<_Tp> volatile* __a, _Tp __val, memory_order __order) _NOEXCEPT { __c11_atomic_store(&__a->__a_value, __val, static_cast<__memory_order_underlying_t>(__order)); } template _LIBCPP_INLINE_VISIBILITY void __cxx_atomic_store(__cxx_atomic_base_impl<_Tp> * __a, _Tp __val, memory_order __order) _NOEXCEPT { __c11_atomic_store(&__a->__a_value, __val, static_cast<__memory_order_underlying_t>(__order)); } template _LIBCPP_INLINE_VISIBILITY _Tp __cxx_atomic_load(__cxx_atomic_base_impl<_Tp> const volatile* __a, memory_order __order) _NOEXCEPT { using __ptr_type = typename remove_const__a_value)>::type*; return __c11_atomic_load(const_cast<__ptr_type>(&__a->__a_value), static_cast<__memory_order_underlying_t>(__order)); } template _LIBCPP_INLINE_VISIBILITY _Tp __cxx_atomic_load(__cxx_atomic_base_impl<_Tp> const* __a, memory_order __order) _NOEXCEPT { using __ptr_type = typename remove_const__a_value)>::type*; return __c11_atomic_load(const_cast<__ptr_type>(&__a->__a_value), static_cast<__memory_order_underlying_t>(__order)); } template _LIBCPP_INLINE_VISIBILITY _Tp __cxx_atomic_exchange(__cxx_atomic_base_impl<_Tp> volatile* __a, _Tp __value, memory_order __order) _NOEXCEPT { return __c11_atomic_exchange(&__a->__a_value, __value, static_cast<__memory_order_underlying_t>(__order)); } template _LIBCPP_INLINE_VISIBILITY _Tp __cxx_atomic_exchange(__cxx_atomic_base_impl<_Tp> * __a, _Tp __value, memory_order __order) _NOEXCEPT { return __c11_atomic_exchange(&__a->__a_value, __value, static_cast<__memory_order_underlying_t>(__order)); } _LIBCPP_INLINE_VISIBILITY inline _LIBCPP_CONSTEXPR memory_order __to_failure_order(memory_order __order) { // Avoid switch statement to make this a constexpr. return __order == memory_order_release ? memory_order_relaxed: (__order == memory_order_acq_rel ? memory_order_acquire: __order); } template _LIBCPP_INLINE_VISIBILITY bool __cxx_atomic_compare_exchange_strong(__cxx_atomic_base_impl<_Tp> volatile* __a, _Tp* __expected, _Tp __value, memory_order __success, memory_order __failure) _NOEXCEPT { return __c11_atomic_compare_exchange_strong(&__a->__a_value, __expected, __value, static_cast<__memory_order_underlying_t>(__success), static_cast<__memory_order_underlying_t>(__to_failure_order(__failure))); } template _LIBCPP_INLINE_VISIBILITY bool __cxx_atomic_compare_exchange_strong(__cxx_atomic_base_impl<_Tp> * __a, _Tp* __expected, _Tp __value, memory_order __success, memory_order __failure) _NOEXCEPT { return __c11_atomic_compare_exchange_strong(&__a->__a_value, __expected, __value, static_cast<__memory_order_underlying_t>(__success), static_cast<__memory_order_underlying_t>(__to_failure_order(__failure))); } template _LIBCPP_INLINE_VISIBILITY bool __cxx_atomic_compare_exchange_weak(__cxx_atomic_base_impl<_Tp> volatile* __a, _Tp* __expected, _Tp __value, memory_order __success, memory_order __failure) _NOEXCEPT { return __c11_atomic_compare_exchange_weak(&__a->__a_value, __expected, __value, static_cast<__memory_order_underlying_t>(__success), static_cast<__memory_order_underlying_t>(__to_failure_order(__failure))); } template _LIBCPP_INLINE_VISIBILITY bool __cxx_atomic_compare_exchange_weak(__cxx_atomic_base_impl<_Tp> * __a, _Tp* __expected, _Tp __value, memory_order __success, memory_order __failure) _NOEXCEPT { return __c11_atomic_compare_exchange_weak(&__a->__a_value, __expected, __value, static_cast<__memory_order_underlying_t>(__success), static_cast<__memory_order_underlying_t>(__to_failure_order(__failure))); } template _LIBCPP_INLINE_VISIBILITY _Tp __cxx_atomic_fetch_add(__cxx_atomic_base_impl<_Tp> volatile* __a, _Tp __delta, memory_order __order) _NOEXCEPT { return __c11_atomic_fetch_add(&__a->__a_value, __delta, static_cast<__memory_order_underlying_t>(__order)); } template _LIBCPP_INLINE_VISIBILITY _Tp __cxx_atomic_fetch_add(__cxx_atomic_base_impl<_Tp> * __a, _Tp __delta, memory_order __order) _NOEXCEPT { return __c11_atomic_fetch_add(&__a->__a_value, __delta, static_cast<__memory_order_underlying_t>(__order)); } template _LIBCPP_INLINE_VISIBILITY _Tp* __cxx_atomic_fetch_add(__cxx_atomic_base_impl<_Tp*> volatile* __a, ptrdiff_t __delta, memory_order __order) _NOEXCEPT { return __c11_atomic_fetch_add(&__a->__a_value, __delta, static_cast<__memory_order_underlying_t>(__order)); } template _LIBCPP_INLINE_VISIBILITY _Tp* __cxx_atomic_fetch_add(__cxx_atomic_base_impl<_Tp*> * __a, ptrdiff_t __delta, memory_order __order) _NOEXCEPT { return __c11_atomic_fetch_add(&__a->__a_value, __delta, static_cast<__memory_order_underlying_t>(__order)); } template _LIBCPP_INLINE_VISIBILITY _Tp __cxx_atomic_fetch_sub(__cxx_atomic_base_impl<_Tp> volatile* __a, _Tp __delta, memory_order __order) _NOEXCEPT { return __c11_atomic_fetch_sub(&__a->__a_value, __delta, static_cast<__memory_order_underlying_t>(__order)); } template _LIBCPP_INLINE_VISIBILITY _Tp __cxx_atomic_fetch_sub(__cxx_atomic_base_impl<_Tp> * __a, _Tp __delta, memory_order __order) _NOEXCEPT { return __c11_atomic_fetch_sub(&__a->__a_value, __delta, static_cast<__memory_order_underlying_t>(__order)); } template _LIBCPP_INLINE_VISIBILITY _Tp* __cxx_atomic_fetch_sub(__cxx_atomic_base_impl<_Tp*> volatile* __a, ptrdiff_t __delta, memory_order __order) _NOEXCEPT { return __c11_atomic_fetch_sub(&__a->__a_value, __delta, static_cast<__memory_order_underlying_t>(__order)); } template _LIBCPP_INLINE_VISIBILITY _Tp* __cxx_atomic_fetch_sub(__cxx_atomic_base_impl<_Tp*> * __a, ptrdiff_t __delta, memory_order __order) _NOEXCEPT { return __c11_atomic_fetch_sub(&__a->__a_value, __delta, static_cast<__memory_order_underlying_t>(__order)); } template _LIBCPP_INLINE_VISIBILITY _Tp __cxx_atomic_fetch_and(__cxx_atomic_base_impl<_Tp> volatile* __a, _Tp __pattern, memory_order __order) _NOEXCEPT { return __c11_atomic_fetch_and(&__a->__a_value, __pattern, static_cast<__memory_order_underlying_t>(__order)); } template _LIBCPP_INLINE_VISIBILITY _Tp __cxx_atomic_fetch_and(__cxx_atomic_base_impl<_Tp> * __a, _Tp __pattern, memory_order __order) _NOEXCEPT { return __c11_atomic_fetch_and(&__a->__a_value, __pattern, static_cast<__memory_order_underlying_t>(__order)); } template _LIBCPP_INLINE_VISIBILITY _Tp __cxx_atomic_fetch_or(__cxx_atomic_base_impl<_Tp> volatile* __a, _Tp __pattern, memory_order __order) _NOEXCEPT { return __c11_atomic_fetch_or(&__a->__a_value, __pattern, static_cast<__memory_order_underlying_t>(__order)); } template _LIBCPP_INLINE_VISIBILITY _Tp __cxx_atomic_fetch_or(__cxx_atomic_base_impl<_Tp> * __a, _Tp __pattern, memory_order __order) _NOEXCEPT { return __c11_atomic_fetch_or(&__a->__a_value, __pattern, static_cast<__memory_order_underlying_t>(__order)); } template _LIBCPP_INLINE_VISIBILITY _Tp __cxx_atomic_fetch_xor(__cxx_atomic_base_impl<_Tp> volatile* __a, _Tp __pattern, memory_order __order) _NOEXCEPT { return __c11_atomic_fetch_xor(&__a->__a_value, __pattern, static_cast<__memory_order_underlying_t>(__order)); } template _LIBCPP_INLINE_VISIBILITY _Tp __cxx_atomic_fetch_xor(__cxx_atomic_base_impl<_Tp> * __a, _Tp __pattern, memory_order __order) _NOEXCEPT { return __c11_atomic_fetch_xor(&__a->__a_value, __pattern, static_cast<__memory_order_underlying_t>(__order)); } #endif // _LIBCPP_HAS_GCC_ATOMIC_IMP, _LIBCPP_HAS_C_ATOMIC_IMP template _LIBCPP_INLINE_VISIBILITY _Tp kill_dependency(_Tp __y) _NOEXCEPT { return __y; } #if defined(__CLANG_ATOMIC_BOOL_LOCK_FREE) # define ATOMIC_BOOL_LOCK_FREE __CLANG_ATOMIC_BOOL_LOCK_FREE # define ATOMIC_CHAR_LOCK_FREE __CLANG_ATOMIC_CHAR_LOCK_FREE #ifndef _LIBCPP_HAS_NO_CHAR8_T # define ATOMIC_CHAR8_T_LOCK_FREE __CLANG_ATOMIC_CHAR8_T_LOCK_FREE #endif # define ATOMIC_CHAR16_T_LOCK_FREE __CLANG_ATOMIC_CHAR16_T_LOCK_FREE # define ATOMIC_CHAR32_T_LOCK_FREE __CLANG_ATOMIC_CHAR32_T_LOCK_FREE # define ATOMIC_WCHAR_T_LOCK_FREE __CLANG_ATOMIC_WCHAR_T_LOCK_FREE # define ATOMIC_SHORT_LOCK_FREE __CLANG_ATOMIC_SHORT_LOCK_FREE # define ATOMIC_INT_LOCK_FREE __CLANG_ATOMIC_INT_LOCK_FREE # define ATOMIC_LONG_LOCK_FREE __CLANG_ATOMIC_LONG_LOCK_FREE # define ATOMIC_LLONG_LOCK_FREE __CLANG_ATOMIC_LLONG_LOCK_FREE # define ATOMIC_POINTER_LOCK_FREE __CLANG_ATOMIC_POINTER_LOCK_FREE #elif defined(__GCC_ATOMIC_BOOL_LOCK_FREE) # define ATOMIC_BOOL_LOCK_FREE __GCC_ATOMIC_BOOL_LOCK_FREE # define ATOMIC_CHAR_LOCK_FREE __GCC_ATOMIC_CHAR_LOCK_FREE #ifndef _LIBCPP_HAS_NO_CHAR8_T # define ATOMIC_CHAR8_T_LOCK_FREE __GCC_ATOMIC_CHAR8_T_LOCK_FREE #endif # define ATOMIC_CHAR16_T_LOCK_FREE __GCC_ATOMIC_CHAR16_T_LOCK_FREE # define ATOMIC_CHAR32_T_LOCK_FREE __GCC_ATOMIC_CHAR32_T_LOCK_FREE # define ATOMIC_WCHAR_T_LOCK_FREE __GCC_ATOMIC_WCHAR_T_LOCK_FREE # define ATOMIC_SHORT_LOCK_FREE __GCC_ATOMIC_SHORT_LOCK_FREE # define ATOMIC_INT_LOCK_FREE __GCC_ATOMIC_INT_LOCK_FREE # define ATOMIC_LONG_LOCK_FREE __GCC_ATOMIC_LONG_LOCK_FREE # define ATOMIC_LLONG_LOCK_FREE __GCC_ATOMIC_LLONG_LOCK_FREE # define ATOMIC_POINTER_LOCK_FREE __GCC_ATOMIC_POINTER_LOCK_FREE #endif #ifdef _LIBCPP_ATOMIC_ONLY_USE_BUILTINS template struct __cxx_atomic_lock_impl { _LIBCPP_INLINE_VISIBILITY __cxx_atomic_lock_impl() _NOEXCEPT : __a_value(), __a_lock(0) {} _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR explicit __cxx_atomic_lock_impl(_Tp value) _NOEXCEPT : __a_value(value), __a_lock(0) {} _Tp __a_value; mutable __cxx_atomic_base_impl<_LIBCPP_ATOMIC_FLAG_TYPE> __a_lock; _LIBCPP_INLINE_VISIBILITY void __lock() const volatile { while(1 == __cxx_atomic_exchange(&__a_lock, _LIBCPP_ATOMIC_FLAG_TYPE(true), memory_order_acquire)) /*spin*/; } _LIBCPP_INLINE_VISIBILITY void __lock() const { while(1 == __cxx_atomic_exchange(&__a_lock, _LIBCPP_ATOMIC_FLAG_TYPE(true), memory_order_acquire)) /*spin*/; } _LIBCPP_INLINE_VISIBILITY void __unlock() const volatile { __cxx_atomic_store(&__a_lock, _LIBCPP_ATOMIC_FLAG_TYPE(false), memory_order_release); } _LIBCPP_INLINE_VISIBILITY void __unlock() const { __cxx_atomic_store(&__a_lock, _LIBCPP_ATOMIC_FLAG_TYPE(false), memory_order_release); } _LIBCPP_INLINE_VISIBILITY _Tp __read() const volatile { __lock(); _Tp __old; __cxx_atomic_assign_volatile(__old, __a_value); __unlock(); return __old; } _LIBCPP_INLINE_VISIBILITY _Tp __read() const { __lock(); _Tp __old = __a_value; __unlock(); return __old; } }; template _LIBCPP_INLINE_VISIBILITY void __cxx_atomic_init(volatile __cxx_atomic_lock_impl<_Tp>* __a, _Tp __val) { __cxx_atomic_assign_volatile(__a->__a_value, __val); } template _LIBCPP_INLINE_VISIBILITY void __cxx_atomic_init(__cxx_atomic_lock_impl<_Tp>* __a, _Tp __val) { __a->__a_value = __val; } template _LIBCPP_INLINE_VISIBILITY void __cxx_atomic_store(volatile __cxx_atomic_lock_impl<_Tp>* __a, _Tp __val, memory_order) { __a->__lock(); __cxx_atomic_assign_volatile(__a->__a_value, __val); __a->__unlock(); } template _LIBCPP_INLINE_VISIBILITY void __cxx_atomic_store(__cxx_atomic_lock_impl<_Tp>* __a, _Tp __val, memory_order) { __a->__lock(); __a->__a_value = __val; __a->__unlock(); } template _LIBCPP_INLINE_VISIBILITY _Tp __cxx_atomic_load(const volatile __cxx_atomic_lock_impl<_Tp>* __a, memory_order) { return __a->__read(); } template _LIBCPP_INLINE_VISIBILITY _Tp __cxx_atomic_load(const __cxx_atomic_lock_impl<_Tp>* __a, memory_order) { return __a->__read(); } template _LIBCPP_INLINE_VISIBILITY _Tp __cxx_atomic_exchange(volatile __cxx_atomic_lock_impl<_Tp>* __a, _Tp __value, memory_order) { __a->__lock(); _Tp __old; __cxx_atomic_assign_volatile(__old, __a->__a_value); __cxx_atomic_assign_volatile(__a->__a_value, __value); __a->__unlock(); return __old; } template _LIBCPP_INLINE_VISIBILITY _Tp __cxx_atomic_exchange(__cxx_atomic_lock_impl<_Tp>* __a, _Tp __value, memory_order) { __a->__lock(); _Tp __old = __a->__a_value; __a->__a_value = __value; __a->__unlock(); return __old; } template _LIBCPP_INLINE_VISIBILITY bool __cxx_atomic_compare_exchange_strong(volatile __cxx_atomic_lock_impl<_Tp>* __a, _Tp* __expected, _Tp __value, memory_order, memory_order) { _Tp __temp; __a->__lock(); __cxx_atomic_assign_volatile(__temp, __a->__a_value); bool __ret = (_VSTD::memcmp(&__temp, __expected, sizeof(_Tp)) == 0); if(__ret) __cxx_atomic_assign_volatile(__a->__a_value, __value); else __cxx_atomic_assign_volatile(*__expected, __a->__a_value); __a->__unlock(); return __ret; } template _LIBCPP_INLINE_VISIBILITY bool __cxx_atomic_compare_exchange_strong(__cxx_atomic_lock_impl<_Tp>* __a, _Tp* __expected, _Tp __value, memory_order, memory_order) { __a->__lock(); bool __ret = (_VSTD::memcmp(&__a->__a_value, __expected, sizeof(_Tp)) == 0); if(__ret) _VSTD::memcpy(&__a->__a_value, &__value, sizeof(_Tp)); else _VSTD::memcpy(__expected, &__a->__a_value, sizeof(_Tp)); __a->__unlock(); return __ret; } template _LIBCPP_INLINE_VISIBILITY bool __cxx_atomic_compare_exchange_weak(volatile __cxx_atomic_lock_impl<_Tp>* __a, _Tp* __expected, _Tp __value, memory_order, memory_order) { _Tp __temp; __a->__lock(); __cxx_atomic_assign_volatile(__temp, __a->__a_value); bool __ret = (_VSTD::memcmp(&__temp, __expected, sizeof(_Tp)) == 0); if(__ret) __cxx_atomic_assign_volatile(__a->__a_value, __value); else __cxx_atomic_assign_volatile(*__expected, __a->__a_value); __a->__unlock(); return __ret; } template _LIBCPP_INLINE_VISIBILITY bool __cxx_atomic_compare_exchange_weak(__cxx_atomic_lock_impl<_Tp>* __a, _Tp* __expected, _Tp __value, memory_order, memory_order) { __a->__lock(); bool __ret = (_VSTD::memcmp(&__a->__a_value, __expected, sizeof(_Tp)) == 0); if(__ret) _VSTD::memcpy(&__a->__a_value, &__value, sizeof(_Tp)); else _VSTD::memcpy(__expected, &__a->__a_value, sizeof(_Tp)); __a->__unlock(); return __ret; } template _LIBCPP_INLINE_VISIBILITY _Tp __cxx_atomic_fetch_add(volatile __cxx_atomic_lock_impl<_Tp>* __a, _Td __delta, memory_order) { __a->__lock(); _Tp __old; __cxx_atomic_assign_volatile(__old, __a->__a_value); __cxx_atomic_assign_volatile(__a->__a_value, _Tp(__old + __delta)); __a->__unlock(); return __old; } template _LIBCPP_INLINE_VISIBILITY _Tp __cxx_atomic_fetch_add(__cxx_atomic_lock_impl<_Tp>* __a, _Td __delta, memory_order) { __a->__lock(); _Tp __old = __a->__a_value; __a->__a_value += __delta; __a->__unlock(); return __old; } template _LIBCPP_INLINE_VISIBILITY _Tp* __cxx_atomic_fetch_add(volatile __cxx_atomic_lock_impl<_Tp*>* __a, ptrdiff_t __delta, memory_order) { __a->__lock(); _Tp* __old; __cxx_atomic_assign_volatile(__old, __a->__a_value); __cxx_atomic_assign_volatile(__a->__a_value, __old + __delta); __a->__unlock(); return __old; } template _LIBCPP_INLINE_VISIBILITY _Tp* __cxx_atomic_fetch_add(__cxx_atomic_lock_impl<_Tp*>* __a, ptrdiff_t __delta, memory_order) { __a->__lock(); _Tp* __old = __a->__a_value; __a->__a_value += __delta; __a->__unlock(); return __old; } template _LIBCPP_INLINE_VISIBILITY _Tp __cxx_atomic_fetch_sub(volatile __cxx_atomic_lock_impl<_Tp>* __a, _Td __delta, memory_order) { __a->__lock(); _Tp __old; __cxx_atomic_assign_volatile(__old, __a->__a_value); __cxx_atomic_assign_volatile(__a->__a_value, _Tp(__old - __delta)); __a->__unlock(); return __old; } template _LIBCPP_INLINE_VISIBILITY _Tp __cxx_atomic_fetch_sub(__cxx_atomic_lock_impl<_Tp>* __a, _Td __delta, memory_order) { __a->__lock(); _Tp __old = __a->__a_value; __a->__a_value -= __delta; __a->__unlock(); return __old; } template _LIBCPP_INLINE_VISIBILITY _Tp __cxx_atomic_fetch_and(volatile __cxx_atomic_lock_impl<_Tp>* __a, _Tp __pattern, memory_order) { __a->__lock(); _Tp __old; __cxx_atomic_assign_volatile(__old, __a->__a_value); __cxx_atomic_assign_volatile(__a->__a_value, _Tp(__old & __pattern)); __a->__unlock(); return __old; } template _LIBCPP_INLINE_VISIBILITY _Tp __cxx_atomic_fetch_and(__cxx_atomic_lock_impl<_Tp>* __a, _Tp __pattern, memory_order) { __a->__lock(); _Tp __old = __a->__a_value; __a->__a_value &= __pattern; __a->__unlock(); return __old; } template _LIBCPP_INLINE_VISIBILITY _Tp __cxx_atomic_fetch_or(volatile __cxx_atomic_lock_impl<_Tp>* __a, _Tp __pattern, memory_order) { __a->__lock(); _Tp __old; __cxx_atomic_assign_volatile(__old, __a->__a_value); __cxx_atomic_assign_volatile(__a->__a_value, _Tp(__old | __pattern)); __a->__unlock(); return __old; } template _LIBCPP_INLINE_VISIBILITY _Tp __cxx_atomic_fetch_or(__cxx_atomic_lock_impl<_Tp>* __a, _Tp __pattern, memory_order) { __a->__lock(); _Tp __old = __a->__a_value; __a->__a_value |= __pattern; __a->__unlock(); return __old; } template _LIBCPP_INLINE_VISIBILITY _Tp __cxx_atomic_fetch_xor(volatile __cxx_atomic_lock_impl<_Tp>* __a, _Tp __pattern, memory_order) { __a->__lock(); _Tp __old; __cxx_atomic_assign_volatile(__old, __a->__a_value); __cxx_atomic_assign_volatile(__a->__a_value, _Tp(__old ^ __pattern)); __a->__unlock(); return __old; } template _LIBCPP_INLINE_VISIBILITY _Tp __cxx_atomic_fetch_xor(__cxx_atomic_lock_impl<_Tp>* __a, _Tp __pattern, memory_order) { __a->__lock(); _Tp __old = __a->__a_value; __a->__a_value ^= __pattern; __a->__unlock(); return __old; } #ifdef __cpp_lib_atomic_is_always_lock_free template struct __cxx_is_always_lock_free { enum { __value = __atomic_always_lock_free(sizeof(_Tp), 0) }; }; #else template struct __cxx_is_always_lock_free { enum { __value = false }; }; // Implementations must match the C ATOMIC_*_LOCK_FREE macro values. template<> struct __cxx_is_always_lock_free { enum { __value = 2 == ATOMIC_BOOL_LOCK_FREE }; }; template<> struct __cxx_is_always_lock_free { enum { __value = 2 == ATOMIC_CHAR_LOCK_FREE }; }; template<> struct __cxx_is_always_lock_free { enum { __value = 2 == ATOMIC_CHAR_LOCK_FREE }; }; template<> struct __cxx_is_always_lock_free { enum { __value = 2 == ATOMIC_CHAR_LOCK_FREE }; }; #ifndef _LIBCPP_HAS_NO_CHAR8_T template<> struct __cxx_is_always_lock_free { enum { __value = 2 == ATOMIC_CHAR8_T_LOCK_FREE }; }; #endif template<> struct __cxx_is_always_lock_free { enum { __value = 2 == ATOMIC_CHAR16_T_LOCK_FREE }; }; template<> struct __cxx_is_always_lock_free { enum { __value = 2 == ATOMIC_CHAR32_T_LOCK_FREE }; }; #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS template<> struct __cxx_is_always_lock_free { enum { __value = 2 == ATOMIC_WCHAR_T_LOCK_FREE }; }; #endif template<> struct __cxx_is_always_lock_free { enum { __value = 2 == ATOMIC_SHORT_LOCK_FREE }; }; template<> struct __cxx_is_always_lock_free { enum { __value = 2 == ATOMIC_SHORT_LOCK_FREE }; }; template<> struct __cxx_is_always_lock_free { enum { __value = 2 == ATOMIC_INT_LOCK_FREE }; }; template<> struct __cxx_is_always_lock_free { enum { __value = 2 == ATOMIC_INT_LOCK_FREE }; }; template<> struct __cxx_is_always_lock_free { enum { __value = 2 == ATOMIC_LONG_LOCK_FREE }; }; template<> struct __cxx_is_always_lock_free { enum { __value = 2 == ATOMIC_LONG_LOCK_FREE }; }; template<> struct __cxx_is_always_lock_free { enum { __value = 2 == ATOMIC_LLONG_LOCK_FREE }; }; template<> struct __cxx_is_always_lock_free { enum { __value = 2 == ATOMIC_LLONG_LOCK_FREE }; }; template struct __cxx_is_always_lock_free<_Tp*> { enum { __value = 2 == ATOMIC_POINTER_LOCK_FREE }; }; template<> struct __cxx_is_always_lock_free { enum { __value = 2 == ATOMIC_POINTER_LOCK_FREE }; }; #endif //__cpp_lib_atomic_is_always_lock_free template ::__value, __cxx_atomic_base_impl<_Tp>, __cxx_atomic_lock_impl<_Tp> >::type> #else template > #endif //_LIBCPP_ATOMIC_ONLY_USE_BUILTINS struct __cxx_atomic_impl : public _Base { static_assert(is_trivially_copyable<_Tp>::value, "std::atomic requires that 'T' be a trivially copyable type"); _LIBCPP_INLINE_VISIBILITY __cxx_atomic_impl() _NOEXCEPT = default; _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR explicit __cxx_atomic_impl(_Tp __value) _NOEXCEPT : _Base(__value) {} }; #if defined(__linux__) || (defined(_AIX) && !defined(__64BIT__)) || \ (defined(__FreeBSD__) && defined(__mips__)) using __cxx_contention_t = int32_t; #else using __cxx_contention_t = int64_t; #endif // __linux__ || (_AIX && !__64BIT__) || (__FreeBSD__ && __mips__) using __cxx_atomic_contention_t = __cxx_atomic_impl<__cxx_contention_t>; #if defined(_LIBCPP_HAS_NO_THREADS) # define _LIBCPP_HAS_NO_PLATFORM_WAIT #endif // TODO: // _LIBCPP_HAS_NO_PLATFORM_WAIT is currently a "dead" macro, in the sense that // it is not tied anywhere into the build system or even documented. We should // clean it up because it is technically never defined except when threads are // disabled. We should clean it up in its own changeset in case we break "bad" // users. #ifndef _LIBCPP_HAS_NO_PLATFORM_WAIT _LIBCPP_AVAILABILITY_SYNC _LIBCPP_EXPORTED_FROM_ABI void __cxx_atomic_notify_one(void const volatile*); _LIBCPP_AVAILABILITY_SYNC _LIBCPP_EXPORTED_FROM_ABI void __cxx_atomic_notify_all(void const volatile*); _LIBCPP_AVAILABILITY_SYNC _LIBCPP_EXPORTED_FROM_ABI __cxx_contention_t __libcpp_atomic_monitor(void const volatile*); _LIBCPP_AVAILABILITY_SYNC _LIBCPP_EXPORTED_FROM_ABI void __libcpp_atomic_wait(void const volatile*, __cxx_contention_t); _LIBCPP_AVAILABILITY_SYNC _LIBCPP_EXPORTED_FROM_ABI void __cxx_atomic_notify_one(__cxx_atomic_contention_t const volatile*); _LIBCPP_AVAILABILITY_SYNC _LIBCPP_EXPORTED_FROM_ABI void __cxx_atomic_notify_all(__cxx_atomic_contention_t const volatile*); _LIBCPP_AVAILABILITY_SYNC _LIBCPP_EXPORTED_FROM_ABI __cxx_contention_t __libcpp_atomic_monitor(__cxx_atomic_contention_t const volatile*); _LIBCPP_AVAILABILITY_SYNC _LIBCPP_EXPORTED_FROM_ABI void __libcpp_atomic_wait(__cxx_atomic_contention_t const volatile*, __cxx_contention_t); template struct __libcpp_atomic_wait_backoff_impl { _Atp* __a; _Fn __test_fn; _LIBCPP_AVAILABILITY_SYNC _LIBCPP_INLINE_VISIBILITY bool operator()(chrono::nanoseconds __elapsed) const { if(__elapsed > chrono::microseconds(64)) { auto const __monitor = __libcpp_atomic_monitor(__a); if(__test_fn()) return true; __libcpp_atomic_wait(__a, __monitor); } else if(__elapsed > chrono::microseconds(4)) __libcpp_thread_yield(); else {} // poll return false; } }; template _LIBCPP_AVAILABILITY_SYNC _LIBCPP_INLINE_VISIBILITY bool __cxx_atomic_wait(_Atp* __a, _Fn && __test_fn) { __libcpp_atomic_wait_backoff_impl<_Atp, typename decay<_Fn>::type> __backoff_fn = {__a, __test_fn}; return __libcpp_thread_poll_with_backoff(__test_fn, __backoff_fn); } #else // _LIBCPP_HAS_NO_PLATFORM_WAIT template _LIBCPP_INLINE_VISIBILITY void __cxx_atomic_notify_all(__cxx_atomic_impl<_Tp> const volatile*) { } template _LIBCPP_INLINE_VISIBILITY void __cxx_atomic_notify_one(__cxx_atomic_impl<_Tp> const volatile*) { } template _LIBCPP_INLINE_VISIBILITY bool __cxx_atomic_wait(_Atp*, _Fn && __test_fn) { #if defined(_LIBCPP_HAS_NO_THREADS) using _Policy = __spinning_backoff_policy; #else using _Policy = __libcpp_timed_backoff_policy; #endif return __libcpp_thread_poll_with_backoff(__test_fn, _Policy()); } #endif // _LIBCPP_HAS_NO_PLATFORM_WAIT template struct __cxx_atomic_wait_test_fn_impl { _Atp* __a; _Tp __val; memory_order __order; _LIBCPP_INLINE_VISIBILITY bool operator()() const { return !__cxx_nonatomic_compare_equal(__cxx_atomic_load(__a, __order), __val); } }; template _LIBCPP_AVAILABILITY_SYNC _LIBCPP_INLINE_VISIBILITY bool __cxx_atomic_wait(_Atp* __a, _Tp const __val, memory_order __order) { __cxx_atomic_wait_test_fn_impl<_Atp, _Tp> __test_fn = {__a, __val, __order}; return __cxx_atomic_wait(__a, __test_fn); } // general atomic template ::value && !is_same<_Tp, bool>::value> struct __atomic_base // false { mutable __cxx_atomic_impl<_Tp> __a_; #if defined(__cpp_lib_atomic_is_always_lock_free) static _LIBCPP_CONSTEXPR bool is_always_lock_free = __atomic_always_lock_free(sizeof(__a_), 0); #endif _LIBCPP_INLINE_VISIBILITY bool is_lock_free() const volatile _NOEXCEPT {return __cxx_atomic_is_lock_free(sizeof(_Tp));} _LIBCPP_INLINE_VISIBILITY bool is_lock_free() const _NOEXCEPT {return static_cast<__atomic_base const volatile*>(this)->is_lock_free();} _LIBCPP_INLINE_VISIBILITY void store(_Tp __d, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT _LIBCPP_CHECK_STORE_MEMORY_ORDER(__m) {__cxx_atomic_store(&__a_, __d, __m);} _LIBCPP_INLINE_VISIBILITY void store(_Tp __d, memory_order __m = memory_order_seq_cst) _NOEXCEPT _LIBCPP_CHECK_STORE_MEMORY_ORDER(__m) {__cxx_atomic_store(&__a_, __d, __m);} _LIBCPP_INLINE_VISIBILITY _Tp load(memory_order __m = memory_order_seq_cst) const volatile _NOEXCEPT _LIBCPP_CHECK_LOAD_MEMORY_ORDER(__m) {return __cxx_atomic_load(&__a_, __m);} _LIBCPP_INLINE_VISIBILITY _Tp load(memory_order __m = memory_order_seq_cst) const _NOEXCEPT _LIBCPP_CHECK_LOAD_MEMORY_ORDER(__m) {return __cxx_atomic_load(&__a_, __m);} _LIBCPP_INLINE_VISIBILITY operator _Tp() const volatile _NOEXCEPT {return load();} _LIBCPP_INLINE_VISIBILITY operator _Tp() const _NOEXCEPT {return load();} _LIBCPP_INLINE_VISIBILITY _Tp exchange(_Tp __d, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT {return __cxx_atomic_exchange(&__a_, __d, __m);} _LIBCPP_INLINE_VISIBILITY _Tp exchange(_Tp __d, memory_order __m = memory_order_seq_cst) _NOEXCEPT {return __cxx_atomic_exchange(&__a_, __d, __m);} _LIBCPP_INLINE_VISIBILITY bool compare_exchange_weak(_Tp& __e, _Tp __d, memory_order __s, memory_order __f) volatile _NOEXCEPT _LIBCPP_CHECK_EXCHANGE_MEMORY_ORDER(__s, __f) {return __cxx_atomic_compare_exchange_weak(&__a_, &__e, __d, __s, __f);} _LIBCPP_INLINE_VISIBILITY bool compare_exchange_weak(_Tp& __e, _Tp __d, memory_order __s, memory_order __f) _NOEXCEPT _LIBCPP_CHECK_EXCHANGE_MEMORY_ORDER(__s, __f) {return __cxx_atomic_compare_exchange_weak(&__a_, &__e, __d, __s, __f);} _LIBCPP_INLINE_VISIBILITY bool compare_exchange_strong(_Tp& __e, _Tp __d, memory_order __s, memory_order __f) volatile _NOEXCEPT _LIBCPP_CHECK_EXCHANGE_MEMORY_ORDER(__s, __f) {return __cxx_atomic_compare_exchange_strong(&__a_, &__e, __d, __s, __f);} _LIBCPP_INLINE_VISIBILITY bool compare_exchange_strong(_Tp& __e, _Tp __d, memory_order __s, memory_order __f) _NOEXCEPT _LIBCPP_CHECK_EXCHANGE_MEMORY_ORDER(__s, __f) {return __cxx_atomic_compare_exchange_strong(&__a_, &__e, __d, __s, __f);} _LIBCPP_INLINE_VISIBILITY bool compare_exchange_weak(_Tp& __e, _Tp __d, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT {return __cxx_atomic_compare_exchange_weak(&__a_, &__e, __d, __m, __m);} _LIBCPP_INLINE_VISIBILITY bool compare_exchange_weak(_Tp& __e, _Tp __d, memory_order __m = memory_order_seq_cst) _NOEXCEPT {return __cxx_atomic_compare_exchange_weak(&__a_, &__e, __d, __m, __m);} _LIBCPP_INLINE_VISIBILITY bool compare_exchange_strong(_Tp& __e, _Tp __d, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT {return __cxx_atomic_compare_exchange_strong(&__a_, &__e, __d, __m, __m);} _LIBCPP_INLINE_VISIBILITY bool compare_exchange_strong(_Tp& __e, _Tp __d, memory_order __m = memory_order_seq_cst) _NOEXCEPT {return __cxx_atomic_compare_exchange_strong(&__a_, &__e, __d, __m, __m);} _LIBCPP_AVAILABILITY_SYNC _LIBCPP_INLINE_VISIBILITY void wait(_Tp __v, memory_order __m = memory_order_seq_cst) const volatile _NOEXCEPT {__cxx_atomic_wait(&__a_, __v, __m);} _LIBCPP_AVAILABILITY_SYNC _LIBCPP_INLINE_VISIBILITY void wait(_Tp __v, memory_order __m = memory_order_seq_cst) const _NOEXCEPT {__cxx_atomic_wait(&__a_, __v, __m);} _LIBCPP_AVAILABILITY_SYNC _LIBCPP_INLINE_VISIBILITY void notify_one() volatile _NOEXCEPT {__cxx_atomic_notify_one(&__a_);} _LIBCPP_AVAILABILITY_SYNC _LIBCPP_INLINE_VISIBILITY void notify_one() _NOEXCEPT {__cxx_atomic_notify_one(&__a_);} _LIBCPP_AVAILABILITY_SYNC _LIBCPP_INLINE_VISIBILITY void notify_all() volatile _NOEXCEPT {__cxx_atomic_notify_all(&__a_);} _LIBCPP_AVAILABILITY_SYNC _LIBCPP_INLINE_VISIBILITY void notify_all() _NOEXCEPT {__cxx_atomic_notify_all(&__a_);} #if _LIBCPP_STD_VER > 17 _LIBCPP_INLINE_VISIBILITY constexpr __atomic_base() noexcept(is_nothrow_default_constructible_v<_Tp>) : __a_(_Tp()) {} #else _LIBCPP_INLINE_VISIBILITY __atomic_base() _NOEXCEPT = default; #endif _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR __atomic_base(_Tp __d) _NOEXCEPT : __a_(__d) {} __atomic_base(const __atomic_base&) = delete; }; #if defined(__cpp_lib_atomic_is_always_lock_free) template _LIBCPP_CONSTEXPR bool __atomic_base<_Tp, __b>::is_always_lock_free; #endif // atomic template struct __atomic_base<_Tp, true> : public __atomic_base<_Tp, false> { typedef __atomic_base<_Tp, false> __base; _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 __atomic_base() _NOEXCEPT = default; _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR __atomic_base(_Tp __d) _NOEXCEPT : __base(__d) {} _LIBCPP_INLINE_VISIBILITY _Tp fetch_add(_Tp __op, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT {return __cxx_atomic_fetch_add(&this->__a_, __op, __m);} _LIBCPP_INLINE_VISIBILITY _Tp fetch_add(_Tp __op, memory_order __m = memory_order_seq_cst) _NOEXCEPT {return __cxx_atomic_fetch_add(&this->__a_, __op, __m);} _LIBCPP_INLINE_VISIBILITY _Tp fetch_sub(_Tp __op, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT {return __cxx_atomic_fetch_sub(&this->__a_, __op, __m);} _LIBCPP_INLINE_VISIBILITY _Tp fetch_sub(_Tp __op, memory_order __m = memory_order_seq_cst) _NOEXCEPT {return __cxx_atomic_fetch_sub(&this->__a_, __op, __m);} _LIBCPP_INLINE_VISIBILITY _Tp fetch_and(_Tp __op, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT {return __cxx_atomic_fetch_and(&this->__a_, __op, __m);} _LIBCPP_INLINE_VISIBILITY _Tp fetch_and(_Tp __op, memory_order __m = memory_order_seq_cst) _NOEXCEPT {return __cxx_atomic_fetch_and(&this->__a_, __op, __m);} _LIBCPP_INLINE_VISIBILITY _Tp fetch_or(_Tp __op, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT {return __cxx_atomic_fetch_or(&this->__a_, __op, __m);} _LIBCPP_INLINE_VISIBILITY _Tp fetch_or(_Tp __op, memory_order __m = memory_order_seq_cst) _NOEXCEPT {return __cxx_atomic_fetch_or(&this->__a_, __op, __m);} _LIBCPP_INLINE_VISIBILITY _Tp fetch_xor(_Tp __op, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT {return __cxx_atomic_fetch_xor(&this->__a_, __op, __m);} _LIBCPP_INLINE_VISIBILITY _Tp fetch_xor(_Tp __op, memory_order __m = memory_order_seq_cst) _NOEXCEPT {return __cxx_atomic_fetch_xor(&this->__a_, __op, __m);} _LIBCPP_INLINE_VISIBILITY _Tp operator++(int) volatile _NOEXCEPT {return fetch_add(_Tp(1));} _LIBCPP_INLINE_VISIBILITY _Tp operator++(int) _NOEXCEPT {return fetch_add(_Tp(1));} _LIBCPP_INLINE_VISIBILITY _Tp operator--(int) volatile _NOEXCEPT {return fetch_sub(_Tp(1));} _LIBCPP_INLINE_VISIBILITY _Tp operator--(int) _NOEXCEPT {return fetch_sub(_Tp(1));} _LIBCPP_INLINE_VISIBILITY _Tp operator++() volatile _NOEXCEPT {return fetch_add(_Tp(1)) + _Tp(1);} _LIBCPP_INLINE_VISIBILITY _Tp operator++() _NOEXCEPT {return fetch_add(_Tp(1)) + _Tp(1);} _LIBCPP_INLINE_VISIBILITY _Tp operator--() volatile _NOEXCEPT {return fetch_sub(_Tp(1)) - _Tp(1);} _LIBCPP_INLINE_VISIBILITY _Tp operator--() _NOEXCEPT {return fetch_sub(_Tp(1)) - _Tp(1);} _LIBCPP_INLINE_VISIBILITY _Tp operator+=(_Tp __op) volatile _NOEXCEPT {return fetch_add(__op) + __op;} _LIBCPP_INLINE_VISIBILITY _Tp operator+=(_Tp __op) _NOEXCEPT {return fetch_add(__op) + __op;} _LIBCPP_INLINE_VISIBILITY _Tp operator-=(_Tp __op) volatile _NOEXCEPT {return fetch_sub(__op) - __op;} _LIBCPP_INLINE_VISIBILITY _Tp operator-=(_Tp __op) _NOEXCEPT {return fetch_sub(__op) - __op;} _LIBCPP_INLINE_VISIBILITY _Tp operator&=(_Tp __op) volatile _NOEXCEPT {return fetch_and(__op) & __op;} _LIBCPP_INLINE_VISIBILITY _Tp operator&=(_Tp __op) _NOEXCEPT {return fetch_and(__op) & __op;} _LIBCPP_INLINE_VISIBILITY _Tp operator|=(_Tp __op) volatile _NOEXCEPT {return fetch_or(__op) | __op;} _LIBCPP_INLINE_VISIBILITY _Tp operator|=(_Tp __op) _NOEXCEPT {return fetch_or(__op) | __op;} _LIBCPP_INLINE_VISIBILITY _Tp operator^=(_Tp __op) volatile _NOEXCEPT {return fetch_xor(__op) ^ __op;} _LIBCPP_INLINE_VISIBILITY _Tp operator^=(_Tp __op) _NOEXCEPT {return fetch_xor(__op) ^ __op;} }; // atomic template struct atomic : public __atomic_base<_Tp> { typedef __atomic_base<_Tp> __base; typedef _Tp value_type; typedef value_type difference_type; #if _LIBCPP_STD_VER > 17 _LIBCPP_INLINE_VISIBILITY atomic() = default; #else _LIBCPP_INLINE_VISIBILITY atomic() _NOEXCEPT = default; #endif _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR atomic(_Tp __d) _NOEXCEPT : __base(__d) {} _LIBCPP_INLINE_VISIBILITY _Tp operator=(_Tp __d) volatile _NOEXCEPT {__base::store(__d); return __d;} _LIBCPP_INLINE_VISIBILITY _Tp operator=(_Tp __d) _NOEXCEPT {__base::store(__d); return __d;} atomic& operator=(const atomic&) = delete; atomic& operator=(const atomic&) volatile = delete; }; // atomic template struct atomic<_Tp*> : public __atomic_base<_Tp*> { typedef __atomic_base<_Tp*> __base; typedef _Tp* value_type; typedef ptrdiff_t difference_type; _LIBCPP_INLINE_VISIBILITY atomic() _NOEXCEPT = default; _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR atomic(_Tp* __d) _NOEXCEPT : __base(__d) {} _LIBCPP_INLINE_VISIBILITY _Tp* operator=(_Tp* __d) volatile _NOEXCEPT {__base::store(__d); return __d;} _LIBCPP_INLINE_VISIBILITY _Tp* operator=(_Tp* __d) _NOEXCEPT {__base::store(__d); return __d;} _LIBCPP_INLINE_VISIBILITY _Tp* fetch_add(ptrdiff_t __op, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT { // __atomic_fetch_add accepts function pointers, guard against them. static_assert(!is_function::type>::value, "Pointer to function isn't allowed"); return __cxx_atomic_fetch_add(&this->__a_, __op, __m); } _LIBCPP_INLINE_VISIBILITY _Tp* fetch_add(ptrdiff_t __op, memory_order __m = memory_order_seq_cst) _NOEXCEPT { // __atomic_fetch_add accepts function pointers, guard against them. static_assert(!is_function::type>::value, "Pointer to function isn't allowed"); return __cxx_atomic_fetch_add(&this->__a_, __op, __m); } _LIBCPP_INLINE_VISIBILITY _Tp* fetch_sub(ptrdiff_t __op, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT { // __atomic_fetch_add accepts function pointers, guard against them. static_assert(!is_function::type>::value, "Pointer to function isn't allowed"); return __cxx_atomic_fetch_sub(&this->__a_, __op, __m); } _LIBCPP_INLINE_VISIBILITY _Tp* fetch_sub(ptrdiff_t __op, memory_order __m = memory_order_seq_cst) _NOEXCEPT { // __atomic_fetch_add accepts function pointers, guard against them. static_assert(!is_function::type>::value, "Pointer to function isn't allowed"); return __cxx_atomic_fetch_sub(&this->__a_, __op, __m); } _LIBCPP_INLINE_VISIBILITY _Tp* operator++(int) volatile _NOEXCEPT {return fetch_add(1);} _LIBCPP_INLINE_VISIBILITY _Tp* operator++(int) _NOEXCEPT {return fetch_add(1);} _LIBCPP_INLINE_VISIBILITY _Tp* operator--(int) volatile _NOEXCEPT {return fetch_sub(1);} _LIBCPP_INLINE_VISIBILITY _Tp* operator--(int) _NOEXCEPT {return fetch_sub(1);} _LIBCPP_INLINE_VISIBILITY _Tp* operator++() volatile _NOEXCEPT {return fetch_add(1) + 1;} _LIBCPP_INLINE_VISIBILITY _Tp* operator++() _NOEXCEPT {return fetch_add(1) + 1;} _LIBCPP_INLINE_VISIBILITY _Tp* operator--() volatile _NOEXCEPT {return fetch_sub(1) - 1;} _LIBCPP_INLINE_VISIBILITY _Tp* operator--() _NOEXCEPT {return fetch_sub(1) - 1;} _LIBCPP_INLINE_VISIBILITY _Tp* operator+=(ptrdiff_t __op) volatile _NOEXCEPT {return fetch_add(__op) + __op;} _LIBCPP_INLINE_VISIBILITY _Tp* operator+=(ptrdiff_t __op) _NOEXCEPT {return fetch_add(__op) + __op;} _LIBCPP_INLINE_VISIBILITY _Tp* operator-=(ptrdiff_t __op) volatile _NOEXCEPT {return fetch_sub(__op) - __op;} _LIBCPP_INLINE_VISIBILITY _Tp* operator-=(ptrdiff_t __op) _NOEXCEPT {return fetch_sub(__op) - __op;} atomic& operator=(const atomic&) = delete; atomic& operator=(const atomic&) volatile = delete; }; // atomic_is_lock_free template _LIBCPP_INLINE_VISIBILITY bool atomic_is_lock_free(const volatile atomic<_Tp>* __o) _NOEXCEPT { return __o->is_lock_free(); } template _LIBCPP_INLINE_VISIBILITY bool atomic_is_lock_free(const atomic<_Tp>* __o) _NOEXCEPT { return __o->is_lock_free(); } // atomic_init template _LIBCPP_DEPRECATED_IN_CXX20 _LIBCPP_INLINE_VISIBILITY void atomic_init(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type __d) _NOEXCEPT { __cxx_atomic_init(&__o->__a_, __d); } template _LIBCPP_DEPRECATED_IN_CXX20 _LIBCPP_INLINE_VISIBILITY void atomic_init(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __d) _NOEXCEPT { __cxx_atomic_init(&__o->__a_, __d); } // atomic_store template _LIBCPP_INLINE_VISIBILITY void atomic_store(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type __d) _NOEXCEPT { __o->store(__d); } template _LIBCPP_INLINE_VISIBILITY void atomic_store(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __d) _NOEXCEPT { __o->store(__d); } // atomic_store_explicit template _LIBCPP_INLINE_VISIBILITY void atomic_store_explicit(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type __d, memory_order __m) _NOEXCEPT _LIBCPP_CHECK_STORE_MEMORY_ORDER(__m) { __o->store(__d, __m); } template _LIBCPP_INLINE_VISIBILITY void atomic_store_explicit(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __d, memory_order __m) _NOEXCEPT _LIBCPP_CHECK_STORE_MEMORY_ORDER(__m) { __o->store(__d, __m); } // atomic_load template _LIBCPP_INLINE_VISIBILITY _Tp atomic_load(const volatile atomic<_Tp>* __o) _NOEXCEPT { return __o->load(); } template _LIBCPP_INLINE_VISIBILITY _Tp atomic_load(const atomic<_Tp>* __o) _NOEXCEPT { return __o->load(); } // atomic_load_explicit template _LIBCPP_INLINE_VISIBILITY _Tp atomic_load_explicit(const volatile atomic<_Tp>* __o, memory_order __m) _NOEXCEPT _LIBCPP_CHECK_LOAD_MEMORY_ORDER(__m) { return __o->load(__m); } template _LIBCPP_INLINE_VISIBILITY _Tp atomic_load_explicit(const atomic<_Tp>* __o, memory_order __m) _NOEXCEPT _LIBCPP_CHECK_LOAD_MEMORY_ORDER(__m) { return __o->load(__m); } // atomic_exchange template _LIBCPP_INLINE_VISIBILITY _Tp atomic_exchange(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type __d) _NOEXCEPT { return __o->exchange(__d); } template _LIBCPP_INLINE_VISIBILITY _Tp atomic_exchange(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __d) _NOEXCEPT { return __o->exchange(__d); } // atomic_exchange_explicit template _LIBCPP_INLINE_VISIBILITY _Tp atomic_exchange_explicit(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type __d, memory_order __m) _NOEXCEPT { return __o->exchange(__d, __m); } template _LIBCPP_INLINE_VISIBILITY _Tp atomic_exchange_explicit(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __d, memory_order __m) _NOEXCEPT { return __o->exchange(__d, __m); } // atomic_compare_exchange_weak template _LIBCPP_INLINE_VISIBILITY bool atomic_compare_exchange_weak(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type* __e, typename atomic<_Tp>::value_type __d) _NOEXCEPT { return __o->compare_exchange_weak(*__e, __d); } template _LIBCPP_INLINE_VISIBILITY bool atomic_compare_exchange_weak(atomic<_Tp>* __o, typename atomic<_Tp>::value_type* __e, typename atomic<_Tp>::value_type __d) _NOEXCEPT { return __o->compare_exchange_weak(*__e, __d); } // atomic_compare_exchange_strong template _LIBCPP_INLINE_VISIBILITY bool atomic_compare_exchange_strong(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type* __e, typename atomic<_Tp>::value_type __d) _NOEXCEPT { return __o->compare_exchange_strong(*__e, __d); } template _LIBCPP_INLINE_VISIBILITY bool atomic_compare_exchange_strong(atomic<_Tp>* __o, typename atomic<_Tp>::value_type* __e, typename atomic<_Tp>::value_type __d) _NOEXCEPT { return __o->compare_exchange_strong(*__e, __d); } // atomic_compare_exchange_weak_explicit template _LIBCPP_INLINE_VISIBILITY bool atomic_compare_exchange_weak_explicit(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type* __e, typename atomic<_Tp>::value_type __d, memory_order __s, memory_order __f) _NOEXCEPT _LIBCPP_CHECK_EXCHANGE_MEMORY_ORDER(__s, __f) { return __o->compare_exchange_weak(*__e, __d, __s, __f); } template _LIBCPP_INLINE_VISIBILITY bool atomic_compare_exchange_weak_explicit(atomic<_Tp>* __o, typename atomic<_Tp>::value_type* __e, typename atomic<_Tp>::value_type __d, memory_order __s, memory_order __f) _NOEXCEPT _LIBCPP_CHECK_EXCHANGE_MEMORY_ORDER(__s, __f) { return __o->compare_exchange_weak(*__e, __d, __s, __f); } // atomic_compare_exchange_strong_explicit template _LIBCPP_INLINE_VISIBILITY bool atomic_compare_exchange_strong_explicit(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type* __e, typename atomic<_Tp>::value_type __d, memory_order __s, memory_order __f) _NOEXCEPT _LIBCPP_CHECK_EXCHANGE_MEMORY_ORDER(__s, __f) { return __o->compare_exchange_strong(*__e, __d, __s, __f); } template _LIBCPP_INLINE_VISIBILITY bool atomic_compare_exchange_strong_explicit(atomic<_Tp>* __o, typename atomic<_Tp>::value_type* __e, typename atomic<_Tp>::value_type __d, memory_order __s, memory_order __f) _NOEXCEPT _LIBCPP_CHECK_EXCHANGE_MEMORY_ORDER(__s, __f) { return __o->compare_exchange_strong(*__e, __d, __s, __f); } // atomic_wait template _LIBCPP_AVAILABILITY_SYNC _LIBCPP_INLINE_VISIBILITY void atomic_wait(const volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type __v) _NOEXCEPT { return __o->wait(__v); } template _LIBCPP_AVAILABILITY_SYNC _LIBCPP_INLINE_VISIBILITY void atomic_wait(const atomic<_Tp>* __o, typename atomic<_Tp>::value_type __v) _NOEXCEPT { return __o->wait(__v); } // atomic_wait_explicit template _LIBCPP_AVAILABILITY_SYNC _LIBCPP_INLINE_VISIBILITY void atomic_wait_explicit(const volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type __v, memory_order __m) _NOEXCEPT _LIBCPP_CHECK_LOAD_MEMORY_ORDER(__m) { return __o->wait(__v, __m); } template _LIBCPP_AVAILABILITY_SYNC _LIBCPP_INLINE_VISIBILITY void atomic_wait_explicit(const atomic<_Tp>* __o, typename atomic<_Tp>::value_type __v, memory_order __m) _NOEXCEPT _LIBCPP_CHECK_LOAD_MEMORY_ORDER(__m) { return __o->wait(__v, __m); } // atomic_notify_one template _LIBCPP_AVAILABILITY_SYNC _LIBCPP_INLINE_VISIBILITY void atomic_notify_one(volatile atomic<_Tp>* __o) _NOEXCEPT { __o->notify_one(); } template _LIBCPP_AVAILABILITY_SYNC _LIBCPP_INLINE_VISIBILITY void atomic_notify_one(atomic<_Tp>* __o) _NOEXCEPT { __o->notify_one(); } // atomic_notify_one template _LIBCPP_AVAILABILITY_SYNC _LIBCPP_INLINE_VISIBILITY void atomic_notify_all(volatile atomic<_Tp>* __o) _NOEXCEPT { __o->notify_all(); } template _LIBCPP_AVAILABILITY_SYNC _LIBCPP_INLINE_VISIBILITY void atomic_notify_all(atomic<_Tp>* __o) _NOEXCEPT { __o->notify_all(); } // atomic_fetch_add template _LIBCPP_INLINE_VISIBILITY _Tp atomic_fetch_add(volatile atomic<_Tp>* __o, typename atomic<_Tp>::difference_type __op) _NOEXCEPT { return __o->fetch_add(__op); } template _LIBCPP_INLINE_VISIBILITY _Tp atomic_fetch_add(atomic<_Tp>* __o, typename atomic<_Tp>::difference_type __op) _NOEXCEPT { return __o->fetch_add(__op); } // atomic_fetch_add_explicit template _LIBCPP_INLINE_VISIBILITY _Tp atomic_fetch_add_explicit(volatile atomic<_Tp>* __o, typename atomic<_Tp>::difference_type __op, memory_order __m) _NOEXCEPT { return __o->fetch_add(__op, __m); } template _LIBCPP_INLINE_VISIBILITY _Tp atomic_fetch_add_explicit(atomic<_Tp>* __o, typename atomic<_Tp>::difference_type __op, memory_order __m) _NOEXCEPT { return __o->fetch_add(__op, __m); } // atomic_fetch_sub template _LIBCPP_INLINE_VISIBILITY _Tp atomic_fetch_sub(volatile atomic<_Tp>* __o, typename atomic<_Tp>::difference_type __op) _NOEXCEPT { return __o->fetch_sub(__op); } template _LIBCPP_INLINE_VISIBILITY _Tp atomic_fetch_sub(atomic<_Tp>* __o, typename atomic<_Tp>::difference_type __op) _NOEXCEPT { return __o->fetch_sub(__op); } // atomic_fetch_sub_explicit template _LIBCPP_INLINE_VISIBILITY _Tp atomic_fetch_sub_explicit(volatile atomic<_Tp>* __o, typename atomic<_Tp>::difference_type __op, memory_order __m) _NOEXCEPT { return __o->fetch_sub(__op, __m); } template _LIBCPP_INLINE_VISIBILITY _Tp atomic_fetch_sub_explicit(atomic<_Tp>* __o, typename atomic<_Tp>::difference_type __op, memory_order __m) _NOEXCEPT { return __o->fetch_sub(__op, __m); } // atomic_fetch_and template _LIBCPP_INLINE_VISIBILITY typename enable_if < is_integral<_Tp>::value && !is_same<_Tp, bool>::value, _Tp >::type atomic_fetch_and(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type __op) _NOEXCEPT { return __o->fetch_and(__op); } template _LIBCPP_INLINE_VISIBILITY typename enable_if < is_integral<_Tp>::value && !is_same<_Tp, bool>::value, _Tp >::type atomic_fetch_and(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __op) _NOEXCEPT { return __o->fetch_and(__op); } // atomic_fetch_and_explicit template _LIBCPP_INLINE_VISIBILITY typename enable_if < is_integral<_Tp>::value && !is_same<_Tp, bool>::value, _Tp >::type atomic_fetch_and_explicit(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type __op, memory_order __m) _NOEXCEPT { return __o->fetch_and(__op, __m); } template _LIBCPP_INLINE_VISIBILITY typename enable_if < is_integral<_Tp>::value && !is_same<_Tp, bool>::value, _Tp >::type atomic_fetch_and_explicit(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __op, memory_order __m) _NOEXCEPT { return __o->fetch_and(__op, __m); } // atomic_fetch_or template _LIBCPP_INLINE_VISIBILITY typename enable_if < is_integral<_Tp>::value && !is_same<_Tp, bool>::value, _Tp >::type atomic_fetch_or(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type __op) _NOEXCEPT { return __o->fetch_or(__op); } template _LIBCPP_INLINE_VISIBILITY typename enable_if < is_integral<_Tp>::value && !is_same<_Tp, bool>::value, _Tp >::type atomic_fetch_or(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __op) _NOEXCEPT { return __o->fetch_or(__op); } // atomic_fetch_or_explicit template _LIBCPP_INLINE_VISIBILITY typename enable_if < is_integral<_Tp>::value && !is_same<_Tp, bool>::value, _Tp >::type atomic_fetch_or_explicit(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type __op, memory_order __m) _NOEXCEPT { return __o->fetch_or(__op, __m); } template _LIBCPP_INLINE_VISIBILITY typename enable_if < is_integral<_Tp>::value && !is_same<_Tp, bool>::value, _Tp >::type atomic_fetch_or_explicit(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __op, memory_order __m) _NOEXCEPT { return __o->fetch_or(__op, __m); } // atomic_fetch_xor template _LIBCPP_INLINE_VISIBILITY typename enable_if < is_integral<_Tp>::value && !is_same<_Tp, bool>::value, _Tp >::type atomic_fetch_xor(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type __op) _NOEXCEPT { return __o->fetch_xor(__op); } template _LIBCPP_INLINE_VISIBILITY typename enable_if < is_integral<_Tp>::value && !is_same<_Tp, bool>::value, _Tp >::type atomic_fetch_xor(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __op) _NOEXCEPT { return __o->fetch_xor(__op); } // atomic_fetch_xor_explicit template _LIBCPP_INLINE_VISIBILITY typename enable_if < is_integral<_Tp>::value && !is_same<_Tp, bool>::value, _Tp >::type atomic_fetch_xor_explicit(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type __op, memory_order __m) _NOEXCEPT { return __o->fetch_xor(__op, __m); } template _LIBCPP_INLINE_VISIBILITY typename enable_if < is_integral<_Tp>::value && !is_same<_Tp, bool>::value, _Tp >::type atomic_fetch_xor_explicit(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __op, memory_order __m) _NOEXCEPT { return __o->fetch_xor(__op, __m); } // flag type and operations typedef struct atomic_flag { __cxx_atomic_impl<_LIBCPP_ATOMIC_FLAG_TYPE> __a_; _LIBCPP_INLINE_VISIBILITY bool test(memory_order __m = memory_order_seq_cst) const volatile _NOEXCEPT {return _LIBCPP_ATOMIC_FLAG_TYPE(true) == __cxx_atomic_load(&__a_, __m);} _LIBCPP_INLINE_VISIBILITY bool test(memory_order __m = memory_order_seq_cst) const _NOEXCEPT {return _LIBCPP_ATOMIC_FLAG_TYPE(true) == __cxx_atomic_load(&__a_, __m);} _LIBCPP_INLINE_VISIBILITY bool test_and_set(memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT {return __cxx_atomic_exchange(&__a_, _LIBCPP_ATOMIC_FLAG_TYPE(true), __m);} _LIBCPP_INLINE_VISIBILITY bool test_and_set(memory_order __m = memory_order_seq_cst) _NOEXCEPT {return __cxx_atomic_exchange(&__a_, _LIBCPP_ATOMIC_FLAG_TYPE(true), __m);} _LIBCPP_INLINE_VISIBILITY void clear(memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT {__cxx_atomic_store(&__a_, _LIBCPP_ATOMIC_FLAG_TYPE(false), __m);} _LIBCPP_INLINE_VISIBILITY void clear(memory_order __m = memory_order_seq_cst) _NOEXCEPT {__cxx_atomic_store(&__a_, _LIBCPP_ATOMIC_FLAG_TYPE(false), __m);} _LIBCPP_AVAILABILITY_SYNC _LIBCPP_INLINE_VISIBILITY void wait(bool __v, memory_order __m = memory_order_seq_cst) const volatile _NOEXCEPT {__cxx_atomic_wait(&__a_, _LIBCPP_ATOMIC_FLAG_TYPE(__v), __m);} _LIBCPP_AVAILABILITY_SYNC _LIBCPP_INLINE_VISIBILITY void wait(bool __v, memory_order __m = memory_order_seq_cst) const _NOEXCEPT {__cxx_atomic_wait(&__a_, _LIBCPP_ATOMIC_FLAG_TYPE(__v), __m);} _LIBCPP_AVAILABILITY_SYNC _LIBCPP_INLINE_VISIBILITY void notify_one() volatile _NOEXCEPT {__cxx_atomic_notify_one(&__a_);} _LIBCPP_AVAILABILITY_SYNC _LIBCPP_INLINE_VISIBILITY void notify_one() _NOEXCEPT {__cxx_atomic_notify_one(&__a_);} _LIBCPP_AVAILABILITY_SYNC _LIBCPP_INLINE_VISIBILITY void notify_all() volatile _NOEXCEPT {__cxx_atomic_notify_all(&__a_);} _LIBCPP_AVAILABILITY_SYNC _LIBCPP_INLINE_VISIBILITY void notify_all() _NOEXCEPT {__cxx_atomic_notify_all(&__a_);} #if _LIBCPP_STD_VER > 17 _LIBCPP_INLINE_VISIBILITY constexpr atomic_flag() _NOEXCEPT : __a_(false) {} #else _LIBCPP_INLINE_VISIBILITY atomic_flag() _NOEXCEPT = default; #endif _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR atomic_flag(bool __b) _NOEXCEPT : __a_(__b) {} // EXTENSION atomic_flag(const atomic_flag&) = delete; atomic_flag& operator=(const atomic_flag&) = delete; atomic_flag& operator=(const atomic_flag&) volatile = delete; } atomic_flag; inline _LIBCPP_INLINE_VISIBILITY bool atomic_flag_test(const volatile atomic_flag* __o) _NOEXCEPT { return __o->test(); } inline _LIBCPP_INLINE_VISIBILITY bool atomic_flag_test(const atomic_flag* __o) _NOEXCEPT { return __o->test(); } inline _LIBCPP_INLINE_VISIBILITY bool atomic_flag_test_explicit(const volatile atomic_flag* __o, memory_order __m) _NOEXCEPT { return __o->test(__m); } inline _LIBCPP_INLINE_VISIBILITY bool atomic_flag_test_explicit(const atomic_flag* __o, memory_order __m) _NOEXCEPT { return __o->test(__m); } inline _LIBCPP_INLINE_VISIBILITY bool atomic_flag_test_and_set(volatile atomic_flag* __o) _NOEXCEPT { return __o->test_and_set(); } inline _LIBCPP_INLINE_VISIBILITY bool atomic_flag_test_and_set(atomic_flag* __o) _NOEXCEPT { return __o->test_and_set(); } inline _LIBCPP_INLINE_VISIBILITY bool atomic_flag_test_and_set_explicit(volatile atomic_flag* __o, memory_order __m) _NOEXCEPT { return __o->test_and_set(__m); } inline _LIBCPP_INLINE_VISIBILITY bool atomic_flag_test_and_set_explicit(atomic_flag* __o, memory_order __m) _NOEXCEPT { return __o->test_and_set(__m); } inline _LIBCPP_INLINE_VISIBILITY void atomic_flag_clear(volatile atomic_flag* __o) _NOEXCEPT { __o->clear(); } inline _LIBCPP_INLINE_VISIBILITY void atomic_flag_clear(atomic_flag* __o) _NOEXCEPT { __o->clear(); } inline _LIBCPP_INLINE_VISIBILITY void atomic_flag_clear_explicit(volatile atomic_flag* __o, memory_order __m) _NOEXCEPT { __o->clear(__m); } inline _LIBCPP_INLINE_VISIBILITY void atomic_flag_clear_explicit(atomic_flag* __o, memory_order __m) _NOEXCEPT { __o->clear(__m); } inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_AVAILABILITY_SYNC void atomic_flag_wait(const volatile atomic_flag* __o, bool __v) _NOEXCEPT { __o->wait(__v); } inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_AVAILABILITY_SYNC void atomic_flag_wait(const atomic_flag* __o, bool __v) _NOEXCEPT { __o->wait(__v); } inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_AVAILABILITY_SYNC void atomic_flag_wait_explicit(const volatile atomic_flag* __o, bool __v, memory_order __m) _NOEXCEPT { __o->wait(__v, __m); } inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_AVAILABILITY_SYNC void atomic_flag_wait_explicit(const atomic_flag* __o, bool __v, memory_order __m) _NOEXCEPT { __o->wait(__v, __m); } inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_AVAILABILITY_SYNC void atomic_flag_notify_one(volatile atomic_flag* __o) _NOEXCEPT { __o->notify_one(); } inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_AVAILABILITY_SYNC void atomic_flag_notify_one(atomic_flag* __o) _NOEXCEPT { __o->notify_one(); } inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_AVAILABILITY_SYNC void atomic_flag_notify_all(volatile atomic_flag* __o) _NOEXCEPT { __o->notify_all(); } inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_AVAILABILITY_SYNC void atomic_flag_notify_all(atomic_flag* __o) _NOEXCEPT { __o->notify_all(); } // fences inline _LIBCPP_INLINE_VISIBILITY void atomic_thread_fence(memory_order __m) _NOEXCEPT { __cxx_atomic_thread_fence(__m); } inline _LIBCPP_INLINE_VISIBILITY void atomic_signal_fence(memory_order __m) _NOEXCEPT { __cxx_atomic_signal_fence(__m); } // Atomics for standard typedef types typedef atomic atomic_bool; typedef atomic atomic_char; typedef atomic atomic_schar; typedef atomic atomic_uchar; typedef atomic atomic_short; typedef atomic atomic_ushort; typedef atomic atomic_int; typedef atomic atomic_uint; typedef atomic atomic_long; typedef atomic atomic_ulong; typedef atomic atomic_llong; typedef atomic atomic_ullong; #ifndef _LIBCPP_HAS_NO_CHAR8_T typedef atomic atomic_char8_t; #endif typedef atomic atomic_char16_t; typedef atomic atomic_char32_t; #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS typedef atomic atomic_wchar_t; #endif typedef atomic atomic_int_least8_t; typedef atomic atomic_uint_least8_t; typedef atomic atomic_int_least16_t; typedef atomic atomic_uint_least16_t; typedef atomic atomic_int_least32_t; typedef atomic atomic_uint_least32_t; typedef atomic atomic_int_least64_t; typedef atomic atomic_uint_least64_t; typedef atomic atomic_int_fast8_t; typedef atomic atomic_uint_fast8_t; typedef atomic atomic_int_fast16_t; typedef atomic atomic_uint_fast16_t; typedef atomic atomic_int_fast32_t; typedef atomic atomic_uint_fast32_t; typedef atomic atomic_int_fast64_t; typedef atomic atomic_uint_fast64_t; typedef atomic< int8_t> atomic_int8_t; typedef atomic atomic_uint8_t; typedef atomic< int16_t> atomic_int16_t; typedef atomic atomic_uint16_t; typedef atomic< int32_t> atomic_int32_t; typedef atomic atomic_uint32_t; typedef atomic< int64_t> atomic_int64_t; typedef atomic atomic_uint64_t; typedef atomic atomic_intptr_t; typedef atomic atomic_uintptr_t; typedef atomic atomic_size_t; typedef atomic atomic_ptrdiff_t; typedef atomic atomic_intmax_t; typedef atomic atomic_uintmax_t; // atomic_*_lock_free : prefer the contention type most highly, then the largest lock-free type #ifdef __cpp_lib_atomic_is_always_lock_free # define _LIBCPP_CONTENTION_LOCK_FREE __atomic_always_lock_free(sizeof(__cxx_contention_t), 0) #else # define _LIBCPP_CONTENTION_LOCK_FREE false #endif #if ATOMIC_LLONG_LOCK_FREE == 2 typedef conditional<_LIBCPP_CONTENTION_LOCK_FREE, __cxx_contention_t, long long>::type __libcpp_signed_lock_free; typedef conditional<_LIBCPP_CONTENTION_LOCK_FREE, __cxx_contention_t, unsigned long long>::type __libcpp_unsigned_lock_free; #elif ATOMIC_INT_LOCK_FREE == 2 typedef conditional<_LIBCPP_CONTENTION_LOCK_FREE, __cxx_contention_t, int>::type __libcpp_signed_lock_free; typedef conditional<_LIBCPP_CONTENTION_LOCK_FREE, __cxx_contention_t, unsigned int>::type __libcpp_unsigned_lock_free; #elif ATOMIC_SHORT_LOCK_FREE == 2 typedef conditional<_LIBCPP_CONTENTION_LOCK_FREE, __cxx_contention_t, short>::type __libcpp_signed_lock_free; typedef conditional<_LIBCPP_CONTENTION_LOCK_FREE, __cxx_contention_t, unsigned short>::type __libcpp_unsigned_lock_free; #elif ATOMIC_CHAR_LOCK_FREE == 2 typedef conditional<_LIBCPP_CONTENTION_LOCK_FREE, __cxx_contention_t, char>::type __libcpp_signed_lock_free; typedef conditional<_LIBCPP_CONTENTION_LOCK_FREE, __cxx_contention_t, unsigned char>::type __libcpp_unsigned_lock_free; #else // No signed/unsigned lock-free types #define _LIBCPP_NO_LOCK_FREE_TYPES #endif #if !defined(_LIBCPP_NO_LOCK_FREE_TYPES) typedef atomic<__libcpp_signed_lock_free> atomic_signed_lock_free; typedef atomic<__libcpp_unsigned_lock_free> atomic_unsigned_lock_free; #endif #define ATOMIC_FLAG_INIT {false} #define ATOMIC_VAR_INIT(__v) {__v} #if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_DISABLE_DEPRECATION_WARNINGS) # if defined(_LIBCPP_CLANG_VER) && _LIBCPP_CLANG_VER >= 1400 # pragma clang deprecated(ATOMIC_VAR_INIT) # endif #endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_DISABLE_DEPRECATION_WARNINGS) _LIBCPP_END_NAMESPACE_STD #endif // _LIBCPP_ATOMIC