Path: blob/main/contrib/llvm-project/libcxx/include/__atomic/atomic.h
35262 views
//===----------------------------------------------------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#ifndef _LIBCPP___ATOMIC_ATOMIC_H9#define _LIBCPP___ATOMIC_ATOMIC_H1011#include <__atomic/atomic_base.h>12#include <__atomic/check_memory_order.h>13#include <__atomic/cxx_atomic_impl.h>14#include <__atomic/memory_order.h>15#include <__config>16#include <__functional/operations.h>17#include <__memory/addressof.h>18#include <__type_traits/is_floating_point.h>19#include <__type_traits/is_function.h>20#include <__type_traits/is_same.h>21#include <__type_traits/remove_const.h>22#include <__type_traits/remove_pointer.h>23#include <__type_traits/remove_volatile.h>24#include <__utility/forward.h>25#include <cstddef>26#include <cstring>2728#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)29# pragma GCC system_header30#endif3132_LIBCPP_BEGIN_NAMESPACE_STD3334template <class _Tp>35struct atomic : public __atomic_base<_Tp> {36using __base = __atomic_base<_Tp>;37using value_type = _Tp;38using difference_type = value_type;3940#if _LIBCPP_STD_VER >= 2041_LIBCPP_HIDE_FROM_ABI atomic() = default;42#else43_LIBCPP_HIDE_FROM_ABI atomic() _NOEXCEPT = default;44#endif4546_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR atomic(_Tp __d) _NOEXCEPT : __base(__d) {}4748_LIBCPP_HIDE_FROM_ABI _Tp operator=(_Tp __d) volatile _NOEXCEPT {49__base::store(__d);50return __d;51}52_LIBCPP_HIDE_FROM_ABI _Tp operator=(_Tp __d) _NOEXCEPT {53__base::store(__d);54return __d;55}5657atomic& operator=(const atomic&) = delete;58atomic& operator=(const atomic&) volatile = delete;59};6061// atomic<T*>6263template <class _Tp>64struct atomic<_Tp*> : public __atomic_base<_Tp*> {65using __base = __atomic_base<_Tp*>;66using value_type = _Tp*;67using difference_type = ptrdiff_t;6869_LIBCPP_HIDE_FROM_ABI atomic() _NOEXCEPT = default;7071_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR atomic(_Tp* __d) _NOEXCEPT : __base(__d) {}7273_LIBCPP_HIDE_FROM_ABI _Tp* operator=(_Tp* __d) volatile _NOEXCEPT {74__base::store(__d);75return __d;76}77_LIBCPP_HIDE_FROM_ABI _Tp* operator=(_Tp* __d) _NOEXCEPT {78__base::store(__d);79return __d;80}8182_LIBCPP_HIDE_FROM_ABI _Tp* fetch_add(ptrdiff_t __op, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT {83// __atomic_fetch_add accepts function pointers, guard against them.84static_assert(!is_function<__remove_pointer_t<_Tp> >::value, "Pointer to function isn't allowed");85return std::__cxx_atomic_fetch_add(std::addressof(this->__a_), __op, __m);86}8788_LIBCPP_HIDE_FROM_ABI _Tp* fetch_add(ptrdiff_t __op, memory_order __m = memory_order_seq_cst) _NOEXCEPT {89// __atomic_fetch_add accepts function pointers, guard against them.90static_assert(!is_function<__remove_pointer_t<_Tp> >::value, "Pointer to function isn't allowed");91return std::__cxx_atomic_fetch_add(std::addressof(this->__a_), __op, __m);92}9394_LIBCPP_HIDE_FROM_ABI _Tp* fetch_sub(ptrdiff_t __op, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT {95// __atomic_fetch_add accepts function pointers, guard against them.96static_assert(!is_function<__remove_pointer_t<_Tp> >::value, "Pointer to function isn't allowed");97return std::__cxx_atomic_fetch_sub(std::addressof(this->__a_), __op, __m);98}99100_LIBCPP_HIDE_FROM_ABI _Tp* fetch_sub(ptrdiff_t __op, memory_order __m = memory_order_seq_cst) _NOEXCEPT {101// __atomic_fetch_add accepts function pointers, guard against them.102static_assert(!is_function<__remove_pointer_t<_Tp> >::value, "Pointer to function isn't allowed");103return std::__cxx_atomic_fetch_sub(std::addressof(this->__a_), __op, __m);104}105106_LIBCPP_HIDE_FROM_ABI _Tp* operator++(int) volatile _NOEXCEPT { return fetch_add(1); }107_LIBCPP_HIDE_FROM_ABI _Tp* operator++(int) _NOEXCEPT { return fetch_add(1); }108_LIBCPP_HIDE_FROM_ABI _Tp* operator--(int) volatile _NOEXCEPT { return fetch_sub(1); }109_LIBCPP_HIDE_FROM_ABI _Tp* operator--(int) _NOEXCEPT { return fetch_sub(1); }110_LIBCPP_HIDE_FROM_ABI _Tp* operator++() volatile _NOEXCEPT { return fetch_add(1) + 1; }111_LIBCPP_HIDE_FROM_ABI _Tp* operator++() _NOEXCEPT { return fetch_add(1) + 1; }112_LIBCPP_HIDE_FROM_ABI _Tp* operator--() volatile _NOEXCEPT { return fetch_sub(1) - 1; }113_LIBCPP_HIDE_FROM_ABI _Tp* operator--() _NOEXCEPT { return fetch_sub(1) - 1; }114_LIBCPP_HIDE_FROM_ABI _Tp* operator+=(ptrdiff_t __op) volatile _NOEXCEPT { return fetch_add(__op) + __op; }115_LIBCPP_HIDE_FROM_ABI _Tp* operator+=(ptrdiff_t __op) _NOEXCEPT { return fetch_add(__op) + __op; }116_LIBCPP_HIDE_FROM_ABI _Tp* operator-=(ptrdiff_t __op) volatile _NOEXCEPT { return fetch_sub(__op) - __op; }117_LIBCPP_HIDE_FROM_ABI _Tp* operator-=(ptrdiff_t __op) _NOEXCEPT { return fetch_sub(__op) - __op; }118119atomic& operator=(const atomic&) = delete;120atomic& operator=(const atomic&) volatile = delete;121};122123#if _LIBCPP_STD_VER >= 20124template <class _Tp>125requires is_floating_point_v<_Tp>126struct atomic<_Tp> : __atomic_base<_Tp> {127private:128_LIBCPP_HIDE_FROM_ABI static constexpr bool __is_fp80_long_double() {129// Only x87-fp80 long double has 64-bit mantissa130return __LDBL_MANT_DIG__ == 64 && std::is_same_v<_Tp, long double>;131}132133_LIBCPP_HIDE_FROM_ABI static constexpr bool __has_rmw_builtin() {134# ifndef _LIBCPP_COMPILER_CLANG_BASED135return false;136# else137// The builtin __cxx_atomic_fetch_add errors during compilation for138// long double on platforms with fp80 format.139// For more details, see140// lib/Sema/SemaChecking.cpp function IsAllowedValueType141// LLVM Parser does not allow atomicrmw with x86_fp80 type.142// if (ValType->isSpecificBuiltinType(BuiltinType::LongDouble) &&143// &Context.getTargetInfo().getLongDoubleFormat() ==144// &llvm::APFloat::x87DoubleExtended())145// For more info146// https://github.com/llvm/llvm-project/issues/68602147// https://reviews.llvm.org/D53965148return !__is_fp80_long_double();149# endif150}151152template <class _This, class _Operation, class _BuiltinOp>153_LIBCPP_HIDE_FROM_ABI static _Tp154__rmw_op(_This&& __self, _Tp __operand, memory_order __m, _Operation __operation, _BuiltinOp __builtin_op) {155if constexpr (__has_rmw_builtin()) {156return __builtin_op(std::addressof(std::forward<_This>(__self).__a_), __operand, __m);157} else {158_Tp __old = __self.load(memory_order_relaxed);159_Tp __new = __operation(__old, __operand);160while (!__self.compare_exchange_weak(__old, __new, __m, memory_order_relaxed)) {161# ifdef _LIBCPP_COMPILER_CLANG_BASED162if constexpr (__is_fp80_long_double()) {163// https://github.com/llvm/llvm-project/issues/47978164// clang bug: __old is not updated on failure for atomic<long double>::compare_exchange_weak165// Note __old = __self.load(memory_order_relaxed) will not work166std::__cxx_atomic_load_inplace(std::addressof(__self.__a_), &__old, memory_order_relaxed);167}168# endif169__new = __operation(__old, __operand);170}171return __old;172}173}174175template <class _This>176_LIBCPP_HIDE_FROM_ABI static _Tp __fetch_add(_This&& __self, _Tp __operand, memory_order __m) {177auto __builtin_op = [](auto __a, auto __builtin_operand, auto __order) {178return std::__cxx_atomic_fetch_add(__a, __builtin_operand, __order);179};180return __rmw_op(std::forward<_This>(__self), __operand, __m, std::plus<>{}, __builtin_op);181}182183template <class _This>184_LIBCPP_HIDE_FROM_ABI static _Tp __fetch_sub(_This&& __self, _Tp __operand, memory_order __m) {185auto __builtin_op = [](auto __a, auto __builtin_operand, auto __order) {186return std::__cxx_atomic_fetch_sub(__a, __builtin_operand, __order);187};188return __rmw_op(std::forward<_This>(__self), __operand, __m, std::minus<>{}, __builtin_op);189}190191public:192using __base = __atomic_base<_Tp>;193using value_type = _Tp;194using difference_type = value_type;195196_LIBCPP_HIDE_FROM_ABI constexpr atomic() noexcept = default;197_LIBCPP_HIDE_FROM_ABI constexpr atomic(_Tp __d) noexcept : __base(__d) {}198199atomic(const atomic&) = delete;200atomic& operator=(const atomic&) = delete;201atomic& operator=(const atomic&) volatile = delete;202203_LIBCPP_HIDE_FROM_ABI _Tp operator=(_Tp __d) volatile noexcept204requires __base::is_always_lock_free205{206__base::store(__d);207return __d;208}209_LIBCPP_HIDE_FROM_ABI _Tp operator=(_Tp __d) noexcept {210__base::store(__d);211return __d;212}213214_LIBCPP_HIDE_FROM_ABI _Tp fetch_add(_Tp __op, memory_order __m = memory_order_seq_cst) volatile noexcept215requires __base::is_always_lock_free216{217return __fetch_add(*this, __op, __m);218}219220_LIBCPP_HIDE_FROM_ABI _Tp fetch_add(_Tp __op, memory_order __m = memory_order_seq_cst) noexcept {221return __fetch_add(*this, __op, __m);222}223224_LIBCPP_HIDE_FROM_ABI _Tp fetch_sub(_Tp __op, memory_order __m = memory_order_seq_cst) volatile noexcept225requires __base::is_always_lock_free226{227return __fetch_sub(*this, __op, __m);228}229230_LIBCPP_HIDE_FROM_ABI _Tp fetch_sub(_Tp __op, memory_order __m = memory_order_seq_cst) noexcept {231return __fetch_sub(*this, __op, __m);232}233234_LIBCPP_HIDE_FROM_ABI _Tp operator+=(_Tp __op) volatile noexcept235requires __base::is_always_lock_free236{237return fetch_add(__op) + __op;238}239240_LIBCPP_HIDE_FROM_ABI _Tp operator+=(_Tp __op) noexcept { return fetch_add(__op) + __op; }241242_LIBCPP_HIDE_FROM_ABI _Tp operator-=(_Tp __op) volatile noexcept243requires __base::is_always_lock_free244{245return fetch_sub(__op) - __op;246}247248_LIBCPP_HIDE_FROM_ABI _Tp operator-=(_Tp __op) noexcept { return fetch_sub(__op) - __op; }249};250251#endif // _LIBCPP_STD_VER >= 20252253// atomic_is_lock_free254255template <class _Tp>256_LIBCPP_HIDE_FROM_ABI bool atomic_is_lock_free(const volatile atomic<_Tp>* __o) _NOEXCEPT {257return __o->is_lock_free();258}259260template <class _Tp>261_LIBCPP_HIDE_FROM_ABI bool atomic_is_lock_free(const atomic<_Tp>* __o) _NOEXCEPT {262return __o->is_lock_free();263}264265// atomic_init266267template <class _Tp>268_LIBCPP_DEPRECATED_IN_CXX20 _LIBCPP_HIDE_FROM_ABI void269atomic_init(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type __d) _NOEXCEPT {270std::__cxx_atomic_init(std::addressof(__o->__a_), __d);271}272273template <class _Tp>274_LIBCPP_DEPRECATED_IN_CXX20 _LIBCPP_HIDE_FROM_ABI void275atomic_init(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __d) _NOEXCEPT {276std::__cxx_atomic_init(std::addressof(__o->__a_), __d);277}278279// atomic_store280281template <class _Tp>282_LIBCPP_HIDE_FROM_ABI void atomic_store(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type __d) _NOEXCEPT {283__o->store(__d);284}285286template <class _Tp>287_LIBCPP_HIDE_FROM_ABI void atomic_store(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __d) _NOEXCEPT {288__o->store(__d);289}290291// atomic_store_explicit292293template <class _Tp>294_LIBCPP_HIDE_FROM_ABI void295atomic_store_explicit(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type __d, memory_order __m) _NOEXCEPT296_LIBCPP_CHECK_STORE_MEMORY_ORDER(__m) {297__o->store(__d, __m);298}299300template <class _Tp>301_LIBCPP_HIDE_FROM_ABI void302atomic_store_explicit(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __d, memory_order __m) _NOEXCEPT303_LIBCPP_CHECK_STORE_MEMORY_ORDER(__m) {304__o->store(__d, __m);305}306307// atomic_load308309template <class _Tp>310_LIBCPP_HIDE_FROM_ABI _Tp atomic_load(const volatile atomic<_Tp>* __o) _NOEXCEPT {311return __o->load();312}313314template <class _Tp>315_LIBCPP_HIDE_FROM_ABI _Tp atomic_load(const atomic<_Tp>* __o) _NOEXCEPT {316return __o->load();317}318319// atomic_load_explicit320321template <class _Tp>322_LIBCPP_HIDE_FROM_ABI _Tp atomic_load_explicit(const volatile atomic<_Tp>* __o, memory_order __m) _NOEXCEPT323_LIBCPP_CHECK_LOAD_MEMORY_ORDER(__m) {324return __o->load(__m);325}326327template <class _Tp>328_LIBCPP_HIDE_FROM_ABI _Tp atomic_load_explicit(const atomic<_Tp>* __o, memory_order __m) _NOEXCEPT329_LIBCPP_CHECK_LOAD_MEMORY_ORDER(__m) {330return __o->load(__m);331}332333// atomic_exchange334335template <class _Tp>336_LIBCPP_HIDE_FROM_ABI _Tp atomic_exchange(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type __d) _NOEXCEPT {337return __o->exchange(__d);338}339340template <class _Tp>341_LIBCPP_HIDE_FROM_ABI _Tp atomic_exchange(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __d) _NOEXCEPT {342return __o->exchange(__d);343}344345// atomic_exchange_explicit346347template <class _Tp>348_LIBCPP_HIDE_FROM_ABI _Tp349atomic_exchange_explicit(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type __d, memory_order __m) _NOEXCEPT {350return __o->exchange(__d, __m);351}352353template <class _Tp>354_LIBCPP_HIDE_FROM_ABI _Tp355atomic_exchange_explicit(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __d, memory_order __m) _NOEXCEPT {356return __o->exchange(__d, __m);357}358359// atomic_compare_exchange_weak360361template <class _Tp>362_LIBCPP_HIDE_FROM_ABI bool atomic_compare_exchange_weak(363volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type* __e, typename atomic<_Tp>::value_type __d) _NOEXCEPT {364return __o->compare_exchange_weak(*__e, __d);365}366367template <class _Tp>368_LIBCPP_HIDE_FROM_ABI bool atomic_compare_exchange_weak(369atomic<_Tp>* __o, typename atomic<_Tp>::value_type* __e, typename atomic<_Tp>::value_type __d) _NOEXCEPT {370return __o->compare_exchange_weak(*__e, __d);371}372373// atomic_compare_exchange_strong374375template <class _Tp>376_LIBCPP_HIDE_FROM_ABI bool atomic_compare_exchange_strong(377volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type* __e, typename atomic<_Tp>::value_type __d) _NOEXCEPT {378return __o->compare_exchange_strong(*__e, __d);379}380381template <class _Tp>382_LIBCPP_HIDE_FROM_ABI bool atomic_compare_exchange_strong(383atomic<_Tp>* __o, typename atomic<_Tp>::value_type* __e, typename atomic<_Tp>::value_type __d) _NOEXCEPT {384return __o->compare_exchange_strong(*__e, __d);385}386387// atomic_compare_exchange_weak_explicit388389template <class _Tp>390_LIBCPP_HIDE_FROM_ABI bool atomic_compare_exchange_weak_explicit(391volatile atomic<_Tp>* __o,392typename atomic<_Tp>::value_type* __e,393typename atomic<_Tp>::value_type __d,394memory_order __s,395memory_order __f) _NOEXCEPT _LIBCPP_CHECK_EXCHANGE_MEMORY_ORDER(__s, __f) {396return __o->compare_exchange_weak(*__e, __d, __s, __f);397}398399template <class _Tp>400_LIBCPP_HIDE_FROM_ABI bool atomic_compare_exchange_weak_explicit(401atomic<_Tp>* __o,402typename atomic<_Tp>::value_type* __e,403typename atomic<_Tp>::value_type __d,404memory_order __s,405memory_order __f) _NOEXCEPT _LIBCPP_CHECK_EXCHANGE_MEMORY_ORDER(__s, __f) {406return __o->compare_exchange_weak(*__e, __d, __s, __f);407}408409// atomic_compare_exchange_strong_explicit410411template <class _Tp>412_LIBCPP_HIDE_FROM_ABI bool atomic_compare_exchange_strong_explicit(413volatile atomic<_Tp>* __o,414typename atomic<_Tp>::value_type* __e,415typename atomic<_Tp>::value_type __d,416memory_order __s,417memory_order __f) _NOEXCEPT _LIBCPP_CHECK_EXCHANGE_MEMORY_ORDER(__s, __f) {418return __o->compare_exchange_strong(*__e, __d, __s, __f);419}420421template <class _Tp>422_LIBCPP_HIDE_FROM_ABI bool atomic_compare_exchange_strong_explicit(423atomic<_Tp>* __o,424typename atomic<_Tp>::value_type* __e,425typename atomic<_Tp>::value_type __d,426memory_order __s,427memory_order __f) _NOEXCEPT _LIBCPP_CHECK_EXCHANGE_MEMORY_ORDER(__s, __f) {428return __o->compare_exchange_strong(*__e, __d, __s, __f);429}430431// atomic_wait432433template <class _Tp>434_LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void435atomic_wait(const volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type __v) _NOEXCEPT {436return __o->wait(__v);437}438439template <class _Tp>440_LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void441atomic_wait(const atomic<_Tp>* __o, typename atomic<_Tp>::value_type __v) _NOEXCEPT {442return __o->wait(__v);443}444445// atomic_wait_explicit446447template <class _Tp>448_LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void449atomic_wait_explicit(const volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type __v, memory_order __m) _NOEXCEPT450_LIBCPP_CHECK_LOAD_MEMORY_ORDER(__m) {451return __o->wait(__v, __m);452}453454template <class _Tp>455_LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void456atomic_wait_explicit(const atomic<_Tp>* __o, typename atomic<_Tp>::value_type __v, memory_order __m) _NOEXCEPT457_LIBCPP_CHECK_LOAD_MEMORY_ORDER(__m) {458return __o->wait(__v, __m);459}460461// atomic_notify_one462463template <class _Tp>464_LIBCPP_DEPRECATED_ATOMIC_SYNC _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void465atomic_notify_one(volatile atomic<_Tp>* __o) _NOEXCEPT {466__o->notify_one();467}468template <class _Tp>469_LIBCPP_DEPRECATED_ATOMIC_SYNC _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void470atomic_notify_one(atomic<_Tp>* __o) _NOEXCEPT {471__o->notify_one();472}473474// atomic_notify_all475476template <class _Tp>477_LIBCPP_DEPRECATED_ATOMIC_SYNC _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void478atomic_notify_all(volatile atomic<_Tp>* __o) _NOEXCEPT {479__o->notify_all();480}481template <class _Tp>482_LIBCPP_DEPRECATED_ATOMIC_SYNC _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void483atomic_notify_all(atomic<_Tp>* __o) _NOEXCEPT {484__o->notify_all();485}486487// atomic_fetch_add488489template <class _Tp>490_LIBCPP_HIDE_FROM_ABI _Tp491atomic_fetch_add(volatile atomic<_Tp>* __o, typename atomic<_Tp>::difference_type __op) _NOEXCEPT {492return __o->fetch_add(__op);493}494495template <class _Tp>496_LIBCPP_HIDE_FROM_ABI _Tp atomic_fetch_add(atomic<_Tp>* __o, typename atomic<_Tp>::difference_type __op) _NOEXCEPT {497return __o->fetch_add(__op);498}499500// atomic_fetch_add_explicit501502template <class _Tp>503_LIBCPP_HIDE_FROM_ABI _Tp atomic_fetch_add_explicit(504volatile atomic<_Tp>* __o, typename atomic<_Tp>::difference_type __op, memory_order __m) _NOEXCEPT {505return __o->fetch_add(__op, __m);506}507508template <class _Tp>509_LIBCPP_HIDE_FROM_ABI _Tp510atomic_fetch_add_explicit(atomic<_Tp>* __o, typename atomic<_Tp>::difference_type __op, memory_order __m) _NOEXCEPT {511return __o->fetch_add(__op, __m);512}513514// atomic_fetch_sub515516template <class _Tp>517_LIBCPP_HIDE_FROM_ABI _Tp518atomic_fetch_sub(volatile atomic<_Tp>* __o, typename atomic<_Tp>::difference_type __op) _NOEXCEPT {519return __o->fetch_sub(__op);520}521522template <class _Tp>523_LIBCPP_HIDE_FROM_ABI _Tp atomic_fetch_sub(atomic<_Tp>* __o, typename atomic<_Tp>::difference_type __op) _NOEXCEPT {524return __o->fetch_sub(__op);525}526527// atomic_fetch_sub_explicit528529template <class _Tp>530_LIBCPP_HIDE_FROM_ABI _Tp atomic_fetch_sub_explicit(531volatile atomic<_Tp>* __o, typename atomic<_Tp>::difference_type __op, memory_order __m) _NOEXCEPT {532return __o->fetch_sub(__op, __m);533}534535template <class _Tp>536_LIBCPP_HIDE_FROM_ABI _Tp537atomic_fetch_sub_explicit(atomic<_Tp>* __o, typename atomic<_Tp>::difference_type __op, memory_order __m) _NOEXCEPT {538return __o->fetch_sub(__op, __m);539}540541// atomic_fetch_and542543template <class _Tp, __enable_if_t<is_integral<_Tp>::value && !is_same<_Tp, bool>::value, int> = 0>544_LIBCPP_HIDE_FROM_ABI _Tp atomic_fetch_and(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type __op) _NOEXCEPT {545return __o->fetch_and(__op);546}547548template <class _Tp, __enable_if_t<is_integral<_Tp>::value && !is_same<_Tp, bool>::value, int> = 0>549_LIBCPP_HIDE_FROM_ABI _Tp atomic_fetch_and(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __op) _NOEXCEPT {550return __o->fetch_and(__op);551}552553// atomic_fetch_and_explicit554555template <class _Tp, __enable_if_t<is_integral<_Tp>::value && !is_same<_Tp, bool>::value, int> = 0>556_LIBCPP_HIDE_FROM_ABI _Tp atomic_fetch_and_explicit(557volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type __op, memory_order __m) _NOEXCEPT {558return __o->fetch_and(__op, __m);559}560561template <class _Tp, __enable_if_t<is_integral<_Tp>::value && !is_same<_Tp, bool>::value, int> = 0>562_LIBCPP_HIDE_FROM_ABI _Tp563atomic_fetch_and_explicit(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __op, memory_order __m) _NOEXCEPT {564return __o->fetch_and(__op, __m);565}566567// atomic_fetch_or568569template <class _Tp, __enable_if_t<is_integral<_Tp>::value && !is_same<_Tp, bool>::value, int> = 0>570_LIBCPP_HIDE_FROM_ABI _Tp atomic_fetch_or(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type __op) _NOEXCEPT {571return __o->fetch_or(__op);572}573574template <class _Tp, __enable_if_t<is_integral<_Tp>::value && !is_same<_Tp, bool>::value, int> = 0>575_LIBCPP_HIDE_FROM_ABI _Tp atomic_fetch_or(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __op) _NOEXCEPT {576return __o->fetch_or(__op);577}578579// atomic_fetch_or_explicit580581template <class _Tp, __enable_if_t<is_integral<_Tp>::value && !is_same<_Tp, bool>::value, int> = 0>582_LIBCPP_HIDE_FROM_ABI _Tp583atomic_fetch_or_explicit(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type __op, memory_order __m) _NOEXCEPT {584return __o->fetch_or(__op, __m);585}586587template <class _Tp, __enable_if_t<is_integral<_Tp>::value && !is_same<_Tp, bool>::value, int> = 0>588_LIBCPP_HIDE_FROM_ABI _Tp589atomic_fetch_or_explicit(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __op, memory_order __m) _NOEXCEPT {590return __o->fetch_or(__op, __m);591}592593// atomic_fetch_xor594595template <class _Tp, __enable_if_t<is_integral<_Tp>::value && !is_same<_Tp, bool>::value, int> = 0>596_LIBCPP_HIDE_FROM_ABI _Tp atomic_fetch_xor(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type __op) _NOEXCEPT {597return __o->fetch_xor(__op);598}599600template <class _Tp, __enable_if_t<is_integral<_Tp>::value && !is_same<_Tp, bool>::value, int> = 0>601_LIBCPP_HIDE_FROM_ABI _Tp atomic_fetch_xor(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __op) _NOEXCEPT {602return __o->fetch_xor(__op);603}604605// atomic_fetch_xor_explicit606607template <class _Tp, __enable_if_t<is_integral<_Tp>::value && !is_same<_Tp, bool>::value, int> = 0>608_LIBCPP_HIDE_FROM_ABI _Tp atomic_fetch_xor_explicit(609volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type __op, memory_order __m) _NOEXCEPT {610return __o->fetch_xor(__op, __m);611}612613template <class _Tp, __enable_if_t<is_integral<_Tp>::value && !is_same<_Tp, bool>::value, int> = 0>614_LIBCPP_HIDE_FROM_ABI _Tp615atomic_fetch_xor_explicit(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __op, memory_order __m) _NOEXCEPT {616return __o->fetch_xor(__op, __m);617}618619_LIBCPP_END_NAMESPACE_STD620621#endif // _LIBCPP___ATOMIC_ATOMIC_H622623624