218 lines · c
1//===----------------------------------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#ifndef _LIBCPP___CXX03___ATOMIC_ATOMIC_BASE_H10#define _LIBCPP___CXX03___ATOMIC_ATOMIC_BASE_H11 12#include <__cxx03/__atomic/atomic_sync.h>13#include <__cxx03/__atomic/check_memory_order.h>14#include <__cxx03/__atomic/cxx_atomic_impl.h>15#include <__cxx03/__atomic/is_always_lock_free.h>16#include <__cxx03/__atomic/memory_order.h>17#include <__cxx03/__config>18#include <__cxx03/__memory/addressof.h>19#include <__cxx03/__type_traits/is_integral.h>20#include <__cxx03/__type_traits/is_nothrow_constructible.h>21#include <__cxx03/__type_traits/is_same.h>22#include <__cxx03/version>23 24#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)25# pragma GCC system_header26#endif27 28_LIBCPP_BEGIN_NAMESPACE_STD29 30template <class _Tp, bool = is_integral<_Tp>::value && !is_same<_Tp, bool>::value>31struct __atomic_base // false32{33 mutable __cxx_atomic_impl<_Tp> __a_;34 35 using value_type = _Tp;36 37 _LIBCPP_HIDE_FROM_ABI bool is_lock_free() const volatile _NOEXCEPT {38 return __cxx_atomic_is_lock_free(sizeof(__cxx_atomic_impl<_Tp>));39 }40 _LIBCPP_HIDE_FROM_ABI bool is_lock_free() const _NOEXCEPT {41 return static_cast<__atomic_base const volatile*>(this)->is_lock_free();42 }43 _LIBCPP_HIDE_FROM_ABI void store(_Tp __d, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT44 _LIBCPP_CHECK_STORE_MEMORY_ORDER(__m) {45 std::__cxx_atomic_store(std::addressof(__a_), __d, __m);46 }47 _LIBCPP_HIDE_FROM_ABI void store(_Tp __d, memory_order __m = memory_order_seq_cst) _NOEXCEPT48 _LIBCPP_CHECK_STORE_MEMORY_ORDER(__m) {49 std::__cxx_atomic_store(std::addressof(__a_), __d, __m);50 }51 _LIBCPP_HIDE_FROM_ABI _Tp load(memory_order __m = memory_order_seq_cst) const volatile _NOEXCEPT52 _LIBCPP_CHECK_LOAD_MEMORY_ORDER(__m) {53 return std::__cxx_atomic_load(std::addressof(__a_), __m);54 }55 _LIBCPP_HIDE_FROM_ABI _Tp load(memory_order __m = memory_order_seq_cst) const _NOEXCEPT56 _LIBCPP_CHECK_LOAD_MEMORY_ORDER(__m) {57 return std::__cxx_atomic_load(std::addressof(__a_), __m);58 }59 _LIBCPP_HIDE_FROM_ABI operator _Tp() const volatile _NOEXCEPT { return load(); }60 _LIBCPP_HIDE_FROM_ABI operator _Tp() const _NOEXCEPT { return load(); }61 _LIBCPP_HIDE_FROM_ABI _Tp exchange(_Tp __d, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT {62 return std::__cxx_atomic_exchange(std::addressof(__a_), __d, __m);63 }64 _LIBCPP_HIDE_FROM_ABI _Tp exchange(_Tp __d, memory_order __m = memory_order_seq_cst) _NOEXCEPT {65 return std::__cxx_atomic_exchange(std::addressof(__a_), __d, __m);66 }67 _LIBCPP_HIDE_FROM_ABI bool68 compare_exchange_weak(_Tp& __e, _Tp __d, memory_order __s, memory_order __f) volatile _NOEXCEPT69 _LIBCPP_CHECK_EXCHANGE_MEMORY_ORDER(__s, __f) {70 return std::__cxx_atomic_compare_exchange_weak(std::addressof(__a_), std::addressof(__e), __d, __s, __f);71 }72 _LIBCPP_HIDE_FROM_ABI bool compare_exchange_weak(_Tp& __e, _Tp __d, memory_order __s, memory_order __f) _NOEXCEPT73 _LIBCPP_CHECK_EXCHANGE_MEMORY_ORDER(__s, __f) {74 return std::__cxx_atomic_compare_exchange_weak(std::addressof(__a_), std::addressof(__e), __d, __s, __f);75 }76 _LIBCPP_HIDE_FROM_ABI bool77 compare_exchange_strong(_Tp& __e, _Tp __d, memory_order __s, memory_order __f) volatile _NOEXCEPT78 _LIBCPP_CHECK_EXCHANGE_MEMORY_ORDER(__s, __f) {79 return std::__cxx_atomic_compare_exchange_strong(std::addressof(__a_), std::addressof(__e), __d, __s, __f);80 }81 _LIBCPP_HIDE_FROM_ABI bool compare_exchange_strong(_Tp& __e, _Tp __d, memory_order __s, memory_order __f) _NOEXCEPT82 _LIBCPP_CHECK_EXCHANGE_MEMORY_ORDER(__s, __f) {83 return std::__cxx_atomic_compare_exchange_strong(std::addressof(__a_), std::addressof(__e), __d, __s, __f);84 }85 _LIBCPP_HIDE_FROM_ABI bool86 compare_exchange_weak(_Tp& __e, _Tp __d, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT {87 return std::__cxx_atomic_compare_exchange_weak(std::addressof(__a_), std::addressof(__e), __d, __m, __m);88 }89 _LIBCPP_HIDE_FROM_ABI bool90 compare_exchange_weak(_Tp& __e, _Tp __d, memory_order __m = memory_order_seq_cst) _NOEXCEPT {91 return std::__cxx_atomic_compare_exchange_weak(std::addressof(__a_), std::addressof(__e), __d, __m, __m);92 }93 _LIBCPP_HIDE_FROM_ABI bool94 compare_exchange_strong(_Tp& __e, _Tp __d, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT {95 return std::__cxx_atomic_compare_exchange_strong(std::addressof(__a_), std::addressof(__e), __d, __m, __m);96 }97 _LIBCPP_HIDE_FROM_ABI bool98 compare_exchange_strong(_Tp& __e, _Tp __d, memory_order __m = memory_order_seq_cst) _NOEXCEPT {99 return std::__cxx_atomic_compare_exchange_strong(std::addressof(__a_), std::addressof(__e), __d, __m, __m);100 }101 102 _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void wait(_Tp __v, memory_order __m = memory_order_seq_cst) const103 volatile _NOEXCEPT {104 std::__atomic_wait(*this, __v, __m);105 }106 _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void107 wait(_Tp __v, memory_order __m = memory_order_seq_cst) const _NOEXCEPT {108 std::__atomic_wait(*this, __v, __m);109 }110 _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void notify_one() volatile _NOEXCEPT {111 std::__atomic_notify_one(*this);112 }113 _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void notify_one() _NOEXCEPT { std::__atomic_notify_one(*this); }114 _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void notify_all() volatile _NOEXCEPT {115 std::__atomic_notify_all(*this);116 }117 _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void notify_all() _NOEXCEPT { std::__atomic_notify_all(*this); }118 119 _LIBCPP_HIDE_FROM_ABI __atomic_base() _NOEXCEPT = default;120 121 _LIBCPP_HIDE_FROM_ABI __atomic_base(_Tp __d) _NOEXCEPT : __a_(__d) {}122 123 __atomic_base(const __atomic_base&) = delete;124};125 126// atomic<Integral>127 128template <class _Tp>129struct __atomic_base<_Tp, true> : public __atomic_base<_Tp, false> {130 using __base = __atomic_base<_Tp, false>;131 132 using difference_type = typename __base::value_type;133 134 _LIBCPP_HIDE_FROM_ABI __atomic_base() _NOEXCEPT = default;135 136 _LIBCPP_HIDE_FROM_ABI __atomic_base(_Tp __d) _NOEXCEPT : __base(__d) {}137 138 _LIBCPP_HIDE_FROM_ABI _Tp fetch_add(_Tp __op, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT {139 return std::__cxx_atomic_fetch_add(std::addressof(this->__a_), __op, __m);140 }141 _LIBCPP_HIDE_FROM_ABI _Tp fetch_add(_Tp __op, memory_order __m = memory_order_seq_cst) _NOEXCEPT {142 return std::__cxx_atomic_fetch_add(std::addressof(this->__a_), __op, __m);143 }144 _LIBCPP_HIDE_FROM_ABI _Tp fetch_sub(_Tp __op, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT {145 return std::__cxx_atomic_fetch_sub(std::addressof(this->__a_), __op, __m);146 }147 _LIBCPP_HIDE_FROM_ABI _Tp fetch_sub(_Tp __op, memory_order __m = memory_order_seq_cst) _NOEXCEPT {148 return std::__cxx_atomic_fetch_sub(std::addressof(this->__a_), __op, __m);149 }150 _LIBCPP_HIDE_FROM_ABI _Tp fetch_and(_Tp __op, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT {151 return std::__cxx_atomic_fetch_and(std::addressof(this->__a_), __op, __m);152 }153 _LIBCPP_HIDE_FROM_ABI _Tp fetch_and(_Tp __op, memory_order __m = memory_order_seq_cst) _NOEXCEPT {154 return std::__cxx_atomic_fetch_and(std::addressof(this->__a_), __op, __m);155 }156 _LIBCPP_HIDE_FROM_ABI _Tp fetch_or(_Tp __op, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT {157 return std::__cxx_atomic_fetch_or(std::addressof(this->__a_), __op, __m);158 }159 _LIBCPP_HIDE_FROM_ABI _Tp fetch_or(_Tp __op, memory_order __m = memory_order_seq_cst) _NOEXCEPT {160 return std::__cxx_atomic_fetch_or(std::addressof(this->__a_), __op, __m);161 }162 _LIBCPP_HIDE_FROM_ABI _Tp fetch_xor(_Tp __op, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT {163 return std::__cxx_atomic_fetch_xor(std::addressof(this->__a_), __op, __m);164 }165 _LIBCPP_HIDE_FROM_ABI _Tp fetch_xor(_Tp __op, memory_order __m = memory_order_seq_cst) _NOEXCEPT {166 return std::__cxx_atomic_fetch_xor(std::addressof(this->__a_), __op, __m);167 }168 169 _LIBCPP_HIDE_FROM_ABI _Tp operator++(int) volatile _NOEXCEPT { return fetch_add(_Tp(1)); }170 _LIBCPP_HIDE_FROM_ABI _Tp operator++(int) _NOEXCEPT { return fetch_add(_Tp(1)); }171 _LIBCPP_HIDE_FROM_ABI _Tp operator--(int) volatile _NOEXCEPT { return fetch_sub(_Tp(1)); }172 _LIBCPP_HIDE_FROM_ABI _Tp operator--(int) _NOEXCEPT { return fetch_sub(_Tp(1)); }173 _LIBCPP_HIDE_FROM_ABI _Tp operator++() volatile _NOEXCEPT { return fetch_add(_Tp(1)) + _Tp(1); }174 _LIBCPP_HIDE_FROM_ABI _Tp operator++() _NOEXCEPT { return fetch_add(_Tp(1)) + _Tp(1); }175 _LIBCPP_HIDE_FROM_ABI _Tp operator--() volatile _NOEXCEPT { return fetch_sub(_Tp(1)) - _Tp(1); }176 _LIBCPP_HIDE_FROM_ABI _Tp operator--() _NOEXCEPT { return fetch_sub(_Tp(1)) - _Tp(1); }177 _LIBCPP_HIDE_FROM_ABI _Tp operator+=(_Tp __op) volatile _NOEXCEPT { return fetch_add(__op) + __op; }178 _LIBCPP_HIDE_FROM_ABI _Tp operator+=(_Tp __op) _NOEXCEPT { return fetch_add(__op) + __op; }179 _LIBCPP_HIDE_FROM_ABI _Tp operator-=(_Tp __op) volatile _NOEXCEPT { return fetch_sub(__op) - __op; }180 _LIBCPP_HIDE_FROM_ABI _Tp operator-=(_Tp __op) _NOEXCEPT { return fetch_sub(__op) - __op; }181 _LIBCPP_HIDE_FROM_ABI _Tp operator&=(_Tp __op) volatile _NOEXCEPT { return fetch_and(__op) & __op; }182 _LIBCPP_HIDE_FROM_ABI _Tp operator&=(_Tp __op) _NOEXCEPT { return fetch_and(__op) & __op; }183 _LIBCPP_HIDE_FROM_ABI _Tp operator|=(_Tp __op) volatile _NOEXCEPT { return fetch_or(__op) | __op; }184 _LIBCPP_HIDE_FROM_ABI _Tp operator|=(_Tp __op) _NOEXCEPT { return fetch_or(__op) | __op; }185 _LIBCPP_HIDE_FROM_ABI _Tp operator^=(_Tp __op) volatile _NOEXCEPT { return fetch_xor(__op) ^ __op; }186 _LIBCPP_HIDE_FROM_ABI _Tp operator^=(_Tp __op) _NOEXCEPT { return fetch_xor(__op) ^ __op; }187};188 189// Here we need _IsIntegral because the default template argument is not enough190// e.g __atomic_base<int> is __atomic_base<int, true>, which inherits from191// __atomic_base<int, false> and the caller of the wait function is192// __atomic_base<int, false>. So specializing __atomic_base<_Tp> does not work193template <class _Tp, bool _IsIntegral>194struct __atomic_waitable_traits<__atomic_base<_Tp, _IsIntegral> > {195 static _LIBCPP_HIDE_FROM_ABI _Tp __atomic_load(const __atomic_base<_Tp, _IsIntegral>& __a, memory_order __order) {196 return __a.load(__order);197 }198 199 static _LIBCPP_HIDE_FROM_ABI _Tp200 __atomic_load(const volatile __atomic_base<_Tp, _IsIntegral>& __this, memory_order __order) {201 return __this.load(__order);202 }203 204 static _LIBCPP_HIDE_FROM_ABI const __cxx_atomic_impl<_Tp>*205 __atomic_contention_address(const __atomic_base<_Tp, _IsIntegral>& __a) {206 return std::addressof(__a.__a_);207 }208 209 static _LIBCPP_HIDE_FROM_ABI const volatile __cxx_atomic_impl<_Tp>*210 __atomic_contention_address(const volatile __atomic_base<_Tp, _IsIntegral>& __this) {211 return std::addressof(__this.__a_);212 }213};214 215_LIBCPP_END_NAMESPACE_STD216 217#endif // _LIBCPP___CXX03___ATOMIC_ATOMIC_BASE_H218