File indexing completed on 2026-05-03 08:13:13
0001
0002
0003
0004
0005
0006
0007
0008
0009 #ifndef _LIBCPP___ATOMIC_ATOMIC_H
0010 #define _LIBCPP___ATOMIC_ATOMIC_H
0011
0012 #include <__atomic/atomic_sync.h>
0013 #include <__atomic/check_memory_order.h>
0014 #include <__atomic/is_always_lock_free.h>
0015 #include <__atomic/memory_order.h>
0016 #include <__atomic/support.h>
0017 #include <__config>
0018 #include <__cstddef/ptrdiff_t.h>
0019 #include <__memory/addressof.h>
0020 #include <__type_traits/enable_if.h>
0021 #include <__type_traits/is_floating_point.h>
0022 #include <__type_traits/is_function.h>
0023 #include <__type_traits/is_integral.h>
0024 #include <__type_traits/is_nothrow_constructible.h>
0025 #include <__type_traits/is_same.h>
0026 #include <__type_traits/remove_const.h>
0027 #include <__type_traits/remove_pointer.h>
0028 #include <__type_traits/remove_volatile.h>
0029 #include <__utility/forward.h>
0030 #include <cstring>
0031
0032 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
0033 # pragma GCC system_header
0034 #endif
0035
0036 _LIBCPP_BEGIN_NAMESPACE_STD
0037
0038 template <class _Tp, bool = is_integral<_Tp>::value && !is_same<_Tp, bool>::value>
0039 struct __atomic_base
0040 {
0041 mutable __cxx_atomic_impl<_Tp> __a_;
0042
0043 #if _LIBCPP_STD_VER >= 17
0044 static constexpr bool is_always_lock_free = __libcpp_is_always_lock_free<__cxx_atomic_impl<_Tp> >::__value;
0045 #endif
0046
0047 _LIBCPP_HIDE_FROM_ABI bool is_lock_free() const volatile _NOEXCEPT {
0048 return __cxx_atomic_is_lock_free(sizeof(__cxx_atomic_impl<_Tp>));
0049 }
0050 _LIBCPP_HIDE_FROM_ABI bool is_lock_free() const _NOEXCEPT {
0051 return static_cast<__atomic_base const volatile*>(this)->is_lock_free();
0052 }
0053 _LIBCPP_HIDE_FROM_ABI void store(_Tp __d, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT
0054 _LIBCPP_CHECK_STORE_MEMORY_ORDER(__m) {
0055 std::__cxx_atomic_store(std::addressof(__a_), __d, __m);
0056 }
0057 _LIBCPP_HIDE_FROM_ABI void store(_Tp __d, memory_order __m = memory_order_seq_cst) _NOEXCEPT
0058 _LIBCPP_CHECK_STORE_MEMORY_ORDER(__m) {
0059 std::__cxx_atomic_store(std::addressof(__a_), __d, __m);
0060 }
0061 _LIBCPP_HIDE_FROM_ABI _Tp load(memory_order __m = memory_order_seq_cst) const volatile _NOEXCEPT
0062 _LIBCPP_CHECK_LOAD_MEMORY_ORDER(__m) {
0063 return std::__cxx_atomic_load(std::addressof(__a_), __m);
0064 }
0065 _LIBCPP_HIDE_FROM_ABI _Tp load(memory_order __m = memory_order_seq_cst) const _NOEXCEPT
0066 _LIBCPP_CHECK_LOAD_MEMORY_ORDER(__m) {
0067 return std::__cxx_atomic_load(std::addressof(__a_), __m);
0068 }
0069 _LIBCPP_HIDE_FROM_ABI operator _Tp() const volatile _NOEXCEPT { return load(); }
0070 _LIBCPP_HIDE_FROM_ABI operator _Tp() const _NOEXCEPT { return load(); }
0071 _LIBCPP_HIDE_FROM_ABI _Tp exchange(_Tp __d, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT {
0072 return std::__cxx_atomic_exchange(std::addressof(__a_), __d, __m);
0073 }
0074 _LIBCPP_HIDE_FROM_ABI _Tp exchange(_Tp __d, memory_order __m = memory_order_seq_cst) _NOEXCEPT {
0075 return std::__cxx_atomic_exchange(std::addressof(__a_), __d, __m);
0076 }
0077 _LIBCPP_HIDE_FROM_ABI bool
0078 compare_exchange_weak(_Tp& __e, _Tp __d, memory_order __s, memory_order __f) volatile _NOEXCEPT
0079 _LIBCPP_CHECK_EXCHANGE_MEMORY_ORDER(__s, __f) {
0080 return std::__cxx_atomic_compare_exchange_weak(std::addressof(__a_), std::addressof(__e), __d, __s, __f);
0081 }
0082 _LIBCPP_HIDE_FROM_ABI bool compare_exchange_weak(_Tp& __e, _Tp __d, memory_order __s, memory_order __f) _NOEXCEPT
0083 _LIBCPP_CHECK_EXCHANGE_MEMORY_ORDER(__s, __f) {
0084 return std::__cxx_atomic_compare_exchange_weak(std::addressof(__a_), std::addressof(__e), __d, __s, __f);
0085 }
0086 _LIBCPP_HIDE_FROM_ABI bool
0087 compare_exchange_strong(_Tp& __e, _Tp __d, memory_order __s, memory_order __f) volatile _NOEXCEPT
0088 _LIBCPP_CHECK_EXCHANGE_MEMORY_ORDER(__s, __f) {
0089 return std::__cxx_atomic_compare_exchange_strong(std::addressof(__a_), std::addressof(__e), __d, __s, __f);
0090 }
0091 _LIBCPP_HIDE_FROM_ABI bool compare_exchange_strong(_Tp& __e, _Tp __d, memory_order __s, memory_order __f) _NOEXCEPT
0092 _LIBCPP_CHECK_EXCHANGE_MEMORY_ORDER(__s, __f) {
0093 return std::__cxx_atomic_compare_exchange_strong(std::addressof(__a_), std::addressof(__e), __d, __s, __f);
0094 }
0095 _LIBCPP_HIDE_FROM_ABI bool
0096 compare_exchange_weak(_Tp& __e, _Tp __d, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT {
0097 return std::__cxx_atomic_compare_exchange_weak(std::addressof(__a_), std::addressof(__e), __d, __m, __m);
0098 }
0099 _LIBCPP_HIDE_FROM_ABI bool
0100 compare_exchange_weak(_Tp& __e, _Tp __d, memory_order __m = memory_order_seq_cst) _NOEXCEPT {
0101 return std::__cxx_atomic_compare_exchange_weak(std::addressof(__a_), std::addressof(__e), __d, __m, __m);
0102 }
0103 _LIBCPP_HIDE_FROM_ABI bool
0104 compare_exchange_strong(_Tp& __e, _Tp __d, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT {
0105 return std::__cxx_atomic_compare_exchange_strong(std::addressof(__a_), std::addressof(__e), __d, __m, __m);
0106 }
0107 _LIBCPP_HIDE_FROM_ABI bool
0108 compare_exchange_strong(_Tp& __e, _Tp __d, memory_order __m = memory_order_seq_cst) _NOEXCEPT {
0109 return std::__cxx_atomic_compare_exchange_strong(std::addressof(__a_), std::addressof(__e), __d, __m, __m);
0110 }
0111
0112 #if _LIBCPP_STD_VER >= 20
0113 _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void wait(_Tp __v, memory_order __m = memory_order_seq_cst) const
0114 volatile _NOEXCEPT {
0115 std::__atomic_wait(*this, __v, __m);
0116 }
0117 _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void
0118 wait(_Tp __v, memory_order __m = memory_order_seq_cst) const _NOEXCEPT {
0119 std::__atomic_wait(*this, __v, __m);
0120 }
0121 _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void notify_one() volatile _NOEXCEPT {
0122 std::__atomic_notify_one(*this);
0123 }
0124 _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void notify_one() _NOEXCEPT { std::__atomic_notify_one(*this); }
0125 _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void notify_all() volatile _NOEXCEPT {
0126 std::__atomic_notify_all(*this);
0127 }
0128 _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void notify_all() _NOEXCEPT { std::__atomic_notify_all(*this); }
0129 #endif
0130
0131 #if _LIBCPP_STD_VER >= 20
0132 _LIBCPP_HIDE_FROM_ABI constexpr __atomic_base() noexcept(is_nothrow_default_constructible_v<_Tp>) : __a_(_Tp()) {}
0133 #else
0134 _LIBCPP_HIDE_FROM_ABI __atomic_base() _NOEXCEPT = default;
0135 #endif
0136
0137 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR __atomic_base(_Tp __d) _NOEXCEPT : __a_(__d) {}
0138
0139 __atomic_base(const __atomic_base&) = delete;
0140 };
0141
0142
0143
0144 template <class _Tp>
0145 struct __atomic_base<_Tp, true> : public __atomic_base<_Tp, false> {
0146 using __base _LIBCPP_NODEBUG = __atomic_base<_Tp, false>;
0147
0148 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __atomic_base() _NOEXCEPT = default;
0149
0150 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR __atomic_base(_Tp __d) _NOEXCEPT : __base(__d) {}
0151
0152 _LIBCPP_HIDE_FROM_ABI _Tp fetch_add(_Tp __op, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT {
0153 return std::__cxx_atomic_fetch_add(std::addressof(this->__a_), __op, __m);
0154 }
0155 _LIBCPP_HIDE_FROM_ABI _Tp fetch_add(_Tp __op, memory_order __m = memory_order_seq_cst) _NOEXCEPT {
0156 return std::__cxx_atomic_fetch_add(std::addressof(this->__a_), __op, __m);
0157 }
0158 _LIBCPP_HIDE_FROM_ABI _Tp fetch_sub(_Tp __op, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT {
0159 return std::__cxx_atomic_fetch_sub(std::addressof(this->__a_), __op, __m);
0160 }
0161 _LIBCPP_HIDE_FROM_ABI _Tp fetch_sub(_Tp __op, memory_order __m = memory_order_seq_cst) _NOEXCEPT {
0162 return std::__cxx_atomic_fetch_sub(std::addressof(this->__a_), __op, __m);
0163 }
0164 _LIBCPP_HIDE_FROM_ABI _Tp fetch_and(_Tp __op, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT {
0165 return std::__cxx_atomic_fetch_and(std::addressof(this->__a_), __op, __m);
0166 }
0167 _LIBCPP_HIDE_FROM_ABI _Tp fetch_and(_Tp __op, memory_order __m = memory_order_seq_cst) _NOEXCEPT {
0168 return std::__cxx_atomic_fetch_and(std::addressof(this->__a_), __op, __m);
0169 }
0170 _LIBCPP_HIDE_FROM_ABI _Tp fetch_or(_Tp __op, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT {
0171 return std::__cxx_atomic_fetch_or(std::addressof(this->__a_), __op, __m);
0172 }
0173 _LIBCPP_HIDE_FROM_ABI _Tp fetch_or(_Tp __op, memory_order __m = memory_order_seq_cst) _NOEXCEPT {
0174 return std::__cxx_atomic_fetch_or(std::addressof(this->__a_), __op, __m);
0175 }
0176 _LIBCPP_HIDE_FROM_ABI _Tp fetch_xor(_Tp __op, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT {
0177 return std::__cxx_atomic_fetch_xor(std::addressof(this->__a_), __op, __m);
0178 }
0179 _LIBCPP_HIDE_FROM_ABI _Tp fetch_xor(_Tp __op, memory_order __m = memory_order_seq_cst) _NOEXCEPT {
0180 return std::__cxx_atomic_fetch_xor(std::addressof(this->__a_), __op, __m);
0181 }
0182
0183 _LIBCPP_HIDE_FROM_ABI _Tp operator++(int) volatile _NOEXCEPT { return fetch_add(_Tp(1)); }
0184 _LIBCPP_HIDE_FROM_ABI _Tp operator++(int) _NOEXCEPT { return fetch_add(_Tp(1)); }
0185 _LIBCPP_HIDE_FROM_ABI _Tp operator--(int) volatile _NOEXCEPT { return fetch_sub(_Tp(1)); }
0186 _LIBCPP_HIDE_FROM_ABI _Tp operator--(int) _NOEXCEPT { return fetch_sub(_Tp(1)); }
0187 _LIBCPP_HIDE_FROM_ABI _Tp operator++() volatile _NOEXCEPT { return fetch_add(_Tp(1)) + _Tp(1); }
0188 _LIBCPP_HIDE_FROM_ABI _Tp operator++() _NOEXCEPT { return fetch_add(_Tp(1)) + _Tp(1); }
0189 _LIBCPP_HIDE_FROM_ABI _Tp operator--() volatile _NOEXCEPT { return fetch_sub(_Tp(1)) - _Tp(1); }
0190 _LIBCPP_HIDE_FROM_ABI _Tp operator--() _NOEXCEPT { return fetch_sub(_Tp(1)) - _Tp(1); }
0191 _LIBCPP_HIDE_FROM_ABI _Tp operator+=(_Tp __op) volatile _NOEXCEPT { return fetch_add(__op) + __op; }
0192 _LIBCPP_HIDE_FROM_ABI _Tp operator+=(_Tp __op) _NOEXCEPT { return fetch_add(__op) + __op; }
0193 _LIBCPP_HIDE_FROM_ABI _Tp operator-=(_Tp __op) volatile _NOEXCEPT { return fetch_sub(__op) - __op; }
0194 _LIBCPP_HIDE_FROM_ABI _Tp operator-=(_Tp __op) _NOEXCEPT { return fetch_sub(__op) - __op; }
0195 _LIBCPP_HIDE_FROM_ABI _Tp operator&=(_Tp __op) volatile _NOEXCEPT { return fetch_and(__op) & __op; }
0196 _LIBCPP_HIDE_FROM_ABI _Tp operator&=(_Tp __op) _NOEXCEPT { return fetch_and(__op) & __op; }
0197 _LIBCPP_HIDE_FROM_ABI _Tp operator|=(_Tp __op) volatile _NOEXCEPT { return fetch_or(__op) | __op; }
0198 _LIBCPP_HIDE_FROM_ABI _Tp operator|=(_Tp __op) _NOEXCEPT { return fetch_or(__op) | __op; }
0199 _LIBCPP_HIDE_FROM_ABI _Tp operator^=(_Tp __op) volatile _NOEXCEPT { return fetch_xor(__op) ^ __op; }
0200 _LIBCPP_HIDE_FROM_ABI _Tp operator^=(_Tp __op) _NOEXCEPT { return fetch_xor(__op) ^ __op; }
0201 };
0202
0203
0204
0205
0206
0207 template <class _Tp, bool _IsIntegral>
0208 struct __atomic_waitable_traits<__atomic_base<_Tp, _IsIntegral> > {
0209 static _LIBCPP_HIDE_FROM_ABI _Tp __atomic_load(const __atomic_base<_Tp, _IsIntegral>& __a, memory_order __order) {
0210 return __a.load(__order);
0211 }
0212
0213 static _LIBCPP_HIDE_FROM_ABI _Tp
0214 __atomic_load(const volatile __atomic_base<_Tp, _IsIntegral>& __this, memory_order __order) {
0215 return __this.load(__order);
0216 }
0217
0218 static _LIBCPP_HIDE_FROM_ABI const __cxx_atomic_impl<_Tp>*
0219 __atomic_contention_address(const __atomic_base<_Tp, _IsIntegral>& __a) {
0220 return std::addressof(__a.__a_);
0221 }
0222
0223 static _LIBCPP_HIDE_FROM_ABI const volatile __cxx_atomic_impl<_Tp>*
0224 __atomic_contention_address(const volatile __atomic_base<_Tp, _IsIntegral>& __this) {
0225 return std::addressof(__this.__a_);
0226 }
0227 };
0228
0229 template <class _Tp>
0230 struct atomic : public __atomic_base<_Tp> {
0231 using __base _LIBCPP_NODEBUG = __atomic_base<_Tp>;
0232 using value_type = _Tp;
0233 using difference_type = value_type;
0234
0235 #if _LIBCPP_STD_VER >= 20
0236 _LIBCPP_HIDE_FROM_ABI atomic() = default;
0237 #else
0238 _LIBCPP_HIDE_FROM_ABI atomic() _NOEXCEPT = default;
0239 #endif
0240
0241 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR atomic(_Tp __d) _NOEXCEPT : __base(__d) {}
0242
0243 _LIBCPP_HIDE_FROM_ABI _Tp operator=(_Tp __d) volatile _NOEXCEPT {
0244 __base::store(__d);
0245 return __d;
0246 }
0247 _LIBCPP_HIDE_FROM_ABI _Tp operator=(_Tp __d) _NOEXCEPT {
0248 __base::store(__d);
0249 return __d;
0250 }
0251
0252 atomic& operator=(const atomic&) = delete;
0253 atomic& operator=(const atomic&) volatile = delete;
0254 };
0255
0256
0257
0258 template <class _Tp>
0259 struct atomic<_Tp*> : public __atomic_base<_Tp*> {
0260 using __base _LIBCPP_NODEBUG = __atomic_base<_Tp*>;
0261 using value_type = _Tp*;
0262 using difference_type = ptrdiff_t;
0263
0264 _LIBCPP_HIDE_FROM_ABI atomic() _NOEXCEPT = default;
0265
0266 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR atomic(_Tp* __d) _NOEXCEPT : __base(__d) {}
0267
0268 _LIBCPP_HIDE_FROM_ABI _Tp* operator=(_Tp* __d) volatile _NOEXCEPT {
0269 __base::store(__d);
0270 return __d;
0271 }
0272 _LIBCPP_HIDE_FROM_ABI _Tp* operator=(_Tp* __d) _NOEXCEPT {
0273 __base::store(__d);
0274 return __d;
0275 }
0276
0277 _LIBCPP_HIDE_FROM_ABI _Tp* fetch_add(ptrdiff_t __op, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT {
0278
0279 static_assert(!is_function<__remove_pointer_t<_Tp> >::value, "Pointer to function isn't allowed");
0280 return std::__cxx_atomic_fetch_add(std::addressof(this->__a_), __op, __m);
0281 }
0282
0283 _LIBCPP_HIDE_FROM_ABI _Tp* fetch_add(ptrdiff_t __op, memory_order __m = memory_order_seq_cst) _NOEXCEPT {
0284
0285 static_assert(!is_function<__remove_pointer_t<_Tp> >::value, "Pointer to function isn't allowed");
0286 return std::__cxx_atomic_fetch_add(std::addressof(this->__a_), __op, __m);
0287 }
0288
0289 _LIBCPP_HIDE_FROM_ABI _Tp* fetch_sub(ptrdiff_t __op, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT {
0290
0291 static_assert(!is_function<__remove_pointer_t<_Tp> >::value, "Pointer to function isn't allowed");
0292 return std::__cxx_atomic_fetch_sub(std::addressof(this->__a_), __op, __m);
0293 }
0294
0295 _LIBCPP_HIDE_FROM_ABI _Tp* fetch_sub(ptrdiff_t __op, memory_order __m = memory_order_seq_cst) _NOEXCEPT {
0296
0297 static_assert(!is_function<__remove_pointer_t<_Tp> >::value, "Pointer to function isn't allowed");
0298 return std::__cxx_atomic_fetch_sub(std::addressof(this->__a_), __op, __m);
0299 }
0300
0301 _LIBCPP_HIDE_FROM_ABI _Tp* operator++(int) volatile _NOEXCEPT { return fetch_add(1); }
0302 _LIBCPP_HIDE_FROM_ABI _Tp* operator++(int) _NOEXCEPT { return fetch_add(1); }
0303 _LIBCPP_HIDE_FROM_ABI _Tp* operator--(int) volatile _NOEXCEPT { return fetch_sub(1); }
0304 _LIBCPP_HIDE_FROM_ABI _Tp* operator--(int) _NOEXCEPT { return fetch_sub(1); }
0305 _LIBCPP_HIDE_FROM_ABI _Tp* operator++() volatile _NOEXCEPT { return fetch_add(1) + 1; }
0306 _LIBCPP_HIDE_FROM_ABI _Tp* operator++() _NOEXCEPT { return fetch_add(1) + 1; }
0307 _LIBCPP_HIDE_FROM_ABI _Tp* operator--() volatile _NOEXCEPT { return fetch_sub(1) - 1; }
0308 _LIBCPP_HIDE_FROM_ABI _Tp* operator--() _NOEXCEPT { return fetch_sub(1) - 1; }
0309 _LIBCPP_HIDE_FROM_ABI _Tp* operator+=(ptrdiff_t __op) volatile _NOEXCEPT { return fetch_add(__op) + __op; }
0310 _LIBCPP_HIDE_FROM_ABI _Tp* operator+=(ptrdiff_t __op) _NOEXCEPT { return fetch_add(__op) + __op; }
0311 _LIBCPP_HIDE_FROM_ABI _Tp* operator-=(ptrdiff_t __op) volatile _NOEXCEPT { return fetch_sub(__op) - __op; }
0312 _LIBCPP_HIDE_FROM_ABI _Tp* operator-=(ptrdiff_t __op) _NOEXCEPT { return fetch_sub(__op) - __op; }
0313
0314 atomic& operator=(const atomic&) = delete;
0315 atomic& operator=(const atomic&) volatile = delete;
0316 };
0317
0318 template <class _Tp>
0319 struct __atomic_waitable_traits<atomic<_Tp> > : __atomic_waitable_traits<__atomic_base<_Tp> > {};
0320
0321 #if _LIBCPP_STD_VER >= 20
0322 template <class _Tp>
0323 requires is_floating_point_v<_Tp>
0324 struct atomic<_Tp> : __atomic_base<_Tp> {
0325 private:
0326 _LIBCPP_HIDE_FROM_ABI static constexpr bool __is_fp80_long_double() {
0327
0328 return __LDBL_MANT_DIG__ == 64 && std::is_same_v<_Tp, long double>;
0329 }
0330
0331 _LIBCPP_HIDE_FROM_ABI static constexpr bool __has_rmw_builtin() {
0332 # ifndef _LIBCPP_COMPILER_CLANG_BASED
0333 return false;
0334 # else
0335
0336
0337
0338
0339
0340
0341
0342
0343
0344
0345
0346 return !__is_fp80_long_double();
0347 # endif
0348 }
0349
0350 template <class _This, class _Operation, class _BuiltinOp>
0351 _LIBCPP_HIDE_FROM_ABI static _Tp
0352 __rmw_op(_This&& __self, _Tp __operand, memory_order __m, _Operation __operation, _BuiltinOp __builtin_op) {
0353 if constexpr (__has_rmw_builtin()) {
0354 return __builtin_op(std::addressof(std::forward<_This>(__self).__a_), __operand, __m);
0355 } else {
0356 _Tp __old = __self.load(memory_order_relaxed);
0357 _Tp __new = __operation(__old, __operand);
0358 while (!__self.compare_exchange_weak(__old, __new, __m, memory_order_relaxed)) {
0359 # ifdef _LIBCPP_COMPILER_CLANG_BASED
0360 if constexpr (__is_fp80_long_double()) {
0361
0362
0363
0364 std::__cxx_atomic_load_inplace(std::addressof(__self.__a_), &__old, memory_order_relaxed);
0365 }
0366 # endif
0367 __new = __operation(__old, __operand);
0368 }
0369 return __old;
0370 }
0371 }
0372
0373 template <class _This>
0374 _LIBCPP_HIDE_FROM_ABI static _Tp __fetch_add(_This&& __self, _Tp __operand, memory_order __m) {
0375 auto __builtin_op = [](auto __a, auto __builtin_operand, auto __order) {
0376 return std::__cxx_atomic_fetch_add(__a, __builtin_operand, __order);
0377 };
0378 auto __plus = [](auto __a, auto __b) { return __a + __b; };
0379 return __rmw_op(std::forward<_This>(__self), __operand, __m, __plus, __builtin_op);
0380 }
0381
0382 template <class _This>
0383 _LIBCPP_HIDE_FROM_ABI static _Tp __fetch_sub(_This&& __self, _Tp __operand, memory_order __m) {
0384 auto __builtin_op = [](auto __a, auto __builtin_operand, auto __order) {
0385 return std::__cxx_atomic_fetch_sub(__a, __builtin_operand, __order);
0386 };
0387 auto __minus = [](auto __a, auto __b) { return __a - __b; };
0388 return __rmw_op(std::forward<_This>(__self), __operand, __m, __minus, __builtin_op);
0389 }
0390
0391 public:
0392 using __base _LIBCPP_NODEBUG = __atomic_base<_Tp>;
0393 using value_type = _Tp;
0394 using difference_type = value_type;
0395
0396 _LIBCPP_HIDE_FROM_ABI constexpr atomic() noexcept = default;
0397 _LIBCPP_HIDE_FROM_ABI constexpr atomic(_Tp __d) noexcept : __base(__d) {}
0398
0399 atomic(const atomic&) = delete;
0400 atomic& operator=(const atomic&) = delete;
0401 atomic& operator=(const atomic&) volatile = delete;
0402
0403 _LIBCPP_HIDE_FROM_ABI _Tp operator=(_Tp __d) volatile noexcept
0404 requires __base::is_always_lock_free
0405 {
0406 __base::store(__d);
0407 return __d;
0408 }
0409 _LIBCPP_HIDE_FROM_ABI _Tp operator=(_Tp __d) noexcept {
0410 __base::store(__d);
0411 return __d;
0412 }
0413
0414 _LIBCPP_HIDE_FROM_ABI _Tp fetch_add(_Tp __op, memory_order __m = memory_order_seq_cst) volatile noexcept
0415 requires __base::is_always_lock_free
0416 {
0417 return __fetch_add(*this, __op, __m);
0418 }
0419
0420 _LIBCPP_HIDE_FROM_ABI _Tp fetch_add(_Tp __op, memory_order __m = memory_order_seq_cst) noexcept {
0421 return __fetch_add(*this, __op, __m);
0422 }
0423
0424 _LIBCPP_HIDE_FROM_ABI _Tp fetch_sub(_Tp __op, memory_order __m = memory_order_seq_cst) volatile noexcept
0425 requires __base::is_always_lock_free
0426 {
0427 return __fetch_sub(*this, __op, __m);
0428 }
0429
0430 _LIBCPP_HIDE_FROM_ABI _Tp fetch_sub(_Tp __op, memory_order __m = memory_order_seq_cst) noexcept {
0431 return __fetch_sub(*this, __op, __m);
0432 }
0433
0434 _LIBCPP_HIDE_FROM_ABI _Tp operator+=(_Tp __op) volatile noexcept
0435 requires __base::is_always_lock_free
0436 {
0437 return fetch_add(__op) + __op;
0438 }
0439
0440 _LIBCPP_HIDE_FROM_ABI _Tp operator+=(_Tp __op) noexcept { return fetch_add(__op) + __op; }
0441
0442 _LIBCPP_HIDE_FROM_ABI _Tp operator-=(_Tp __op) volatile noexcept
0443 requires __base::is_always_lock_free
0444 {
0445 return fetch_sub(__op) - __op;
0446 }
0447
0448 _LIBCPP_HIDE_FROM_ABI _Tp operator-=(_Tp __op) noexcept { return fetch_sub(__op) - __op; }
0449 };
0450
0451 #endif
0452
0453
0454
0455 template <class _Tp>
0456 _LIBCPP_HIDE_FROM_ABI bool atomic_is_lock_free(const volatile atomic<_Tp>* __o) _NOEXCEPT {
0457 return __o->is_lock_free();
0458 }
0459
0460 template <class _Tp>
0461 _LIBCPP_HIDE_FROM_ABI bool atomic_is_lock_free(const atomic<_Tp>* __o) _NOEXCEPT {
0462 return __o->is_lock_free();
0463 }
0464
0465
0466
0467 template <class _Tp>
0468 _LIBCPP_DEPRECATED_IN_CXX20 _LIBCPP_HIDE_FROM_ABI void
0469 atomic_init(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type __d) _NOEXCEPT {
0470 std::__cxx_atomic_init(std::addressof(__o->__a_), __d);
0471 }
0472
0473 template <class _Tp>
0474 _LIBCPP_DEPRECATED_IN_CXX20 _LIBCPP_HIDE_FROM_ABI void
0475 atomic_init(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __d) _NOEXCEPT {
0476 std::__cxx_atomic_init(std::addressof(__o->__a_), __d);
0477 }
0478
0479
0480
0481 template <class _Tp>
0482 _LIBCPP_HIDE_FROM_ABI void atomic_store(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type __d) _NOEXCEPT {
0483 __o->store(__d);
0484 }
0485
0486 template <class _Tp>
0487 _LIBCPP_HIDE_FROM_ABI void atomic_store(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __d) _NOEXCEPT {
0488 __o->store(__d);
0489 }
0490
0491
0492
0493 template <class _Tp>
0494 _LIBCPP_HIDE_FROM_ABI void
0495 atomic_store_explicit(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type __d, memory_order __m) _NOEXCEPT
0496 _LIBCPP_CHECK_STORE_MEMORY_ORDER(__m) {
0497 __o->store(__d, __m);
0498 }
0499
0500 template <class _Tp>
0501 _LIBCPP_HIDE_FROM_ABI void
0502 atomic_store_explicit(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __d, memory_order __m) _NOEXCEPT
0503 _LIBCPP_CHECK_STORE_MEMORY_ORDER(__m) {
0504 __o->store(__d, __m);
0505 }
0506
0507
0508
0509 template <class _Tp>
0510 _LIBCPP_HIDE_FROM_ABI _Tp atomic_load(const volatile atomic<_Tp>* __o) _NOEXCEPT {
0511 return __o->load();
0512 }
0513
0514 template <class _Tp>
0515 _LIBCPP_HIDE_FROM_ABI _Tp atomic_load(const atomic<_Tp>* __o) _NOEXCEPT {
0516 return __o->load();
0517 }
0518
0519
0520
0521 template <class _Tp>
0522 _LIBCPP_HIDE_FROM_ABI _Tp atomic_load_explicit(const volatile atomic<_Tp>* __o, memory_order __m) _NOEXCEPT
0523 _LIBCPP_CHECK_LOAD_MEMORY_ORDER(__m) {
0524 return __o->load(__m);
0525 }
0526
0527 template <class _Tp>
0528 _LIBCPP_HIDE_FROM_ABI _Tp atomic_load_explicit(const atomic<_Tp>* __o, memory_order __m) _NOEXCEPT
0529 _LIBCPP_CHECK_LOAD_MEMORY_ORDER(__m) {
0530 return __o->load(__m);
0531 }
0532
0533
0534
0535 template <class _Tp>
0536 _LIBCPP_HIDE_FROM_ABI _Tp atomic_exchange(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type __d) _NOEXCEPT {
0537 return __o->exchange(__d);
0538 }
0539
0540 template <class _Tp>
0541 _LIBCPP_HIDE_FROM_ABI _Tp atomic_exchange(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __d) _NOEXCEPT {
0542 return __o->exchange(__d);
0543 }
0544
0545
0546
0547 template <class _Tp>
0548 _LIBCPP_HIDE_FROM_ABI _Tp
0549 atomic_exchange_explicit(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type __d, memory_order __m) _NOEXCEPT {
0550 return __o->exchange(__d, __m);
0551 }
0552
0553 template <class _Tp>
0554 _LIBCPP_HIDE_FROM_ABI _Tp
0555 atomic_exchange_explicit(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __d, memory_order __m) _NOEXCEPT {
0556 return __o->exchange(__d, __m);
0557 }
0558
0559
0560
0561 template <class _Tp>
0562 _LIBCPP_HIDE_FROM_ABI bool atomic_compare_exchange_weak(
0563 volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type* __e, typename atomic<_Tp>::value_type __d) _NOEXCEPT {
0564 return __o->compare_exchange_weak(*__e, __d);
0565 }
0566
0567 template <class _Tp>
0568 _LIBCPP_HIDE_FROM_ABI bool atomic_compare_exchange_weak(
0569 atomic<_Tp>* __o, typename atomic<_Tp>::value_type* __e, typename atomic<_Tp>::value_type __d) _NOEXCEPT {
0570 return __o->compare_exchange_weak(*__e, __d);
0571 }
0572
0573
0574
0575 template <class _Tp>
0576 _LIBCPP_HIDE_FROM_ABI bool atomic_compare_exchange_strong(
0577 volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type* __e, typename atomic<_Tp>::value_type __d) _NOEXCEPT {
0578 return __o->compare_exchange_strong(*__e, __d);
0579 }
0580
0581 template <class _Tp>
0582 _LIBCPP_HIDE_FROM_ABI bool atomic_compare_exchange_strong(
0583 atomic<_Tp>* __o, typename atomic<_Tp>::value_type* __e, typename atomic<_Tp>::value_type __d) _NOEXCEPT {
0584 return __o->compare_exchange_strong(*__e, __d);
0585 }
0586
0587
0588
0589 template <class _Tp>
0590 _LIBCPP_HIDE_FROM_ABI bool atomic_compare_exchange_weak_explicit(
0591 volatile atomic<_Tp>* __o,
0592 typename atomic<_Tp>::value_type* __e,
0593 typename atomic<_Tp>::value_type __d,
0594 memory_order __s,
0595 memory_order __f) _NOEXCEPT _LIBCPP_CHECK_EXCHANGE_MEMORY_ORDER(__s, __f) {
0596 return __o->compare_exchange_weak(*__e, __d, __s, __f);
0597 }
0598
0599 template <class _Tp>
0600 _LIBCPP_HIDE_FROM_ABI bool atomic_compare_exchange_weak_explicit(
0601 atomic<_Tp>* __o,
0602 typename atomic<_Tp>::value_type* __e,
0603 typename atomic<_Tp>::value_type __d,
0604 memory_order __s,
0605 memory_order __f) _NOEXCEPT _LIBCPP_CHECK_EXCHANGE_MEMORY_ORDER(__s, __f) {
0606 return __o->compare_exchange_weak(*__e, __d, __s, __f);
0607 }
0608
0609
0610
0611 template <class _Tp>
0612 _LIBCPP_HIDE_FROM_ABI bool atomic_compare_exchange_strong_explicit(
0613 volatile atomic<_Tp>* __o,
0614 typename atomic<_Tp>::value_type* __e,
0615 typename atomic<_Tp>::value_type __d,
0616 memory_order __s,
0617 memory_order __f) _NOEXCEPT _LIBCPP_CHECK_EXCHANGE_MEMORY_ORDER(__s, __f) {
0618 return __o->compare_exchange_strong(*__e, __d, __s, __f);
0619 }
0620
0621 template <class _Tp>
0622 _LIBCPP_HIDE_FROM_ABI bool atomic_compare_exchange_strong_explicit(
0623 atomic<_Tp>* __o,
0624 typename atomic<_Tp>::value_type* __e,
0625 typename atomic<_Tp>::value_type __d,
0626 memory_order __s,
0627 memory_order __f) _NOEXCEPT _LIBCPP_CHECK_EXCHANGE_MEMORY_ORDER(__s, __f) {
0628 return __o->compare_exchange_strong(*__e, __d, __s, __f);
0629 }
0630
0631 #if _LIBCPP_STD_VER >= 20
0632
0633
0634
0635 template <class _Tp>
0636 _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void
0637 atomic_wait(const volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type __v) _NOEXCEPT {
0638 return __o->wait(__v);
0639 }
0640
0641 template <class _Tp>
0642 _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void
0643 atomic_wait(const atomic<_Tp>* __o, typename atomic<_Tp>::value_type __v) _NOEXCEPT {
0644 return __o->wait(__v);
0645 }
0646
0647
0648
0649 template <class _Tp>
0650 _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void
0651 atomic_wait_explicit(const volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type __v, memory_order __m) _NOEXCEPT
0652 _LIBCPP_CHECK_LOAD_MEMORY_ORDER(__m) {
0653 return __o->wait(__v, __m);
0654 }
0655
0656 template <class _Tp>
0657 _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void
0658 atomic_wait_explicit(const atomic<_Tp>* __o, typename atomic<_Tp>::value_type __v, memory_order __m) _NOEXCEPT
0659 _LIBCPP_CHECK_LOAD_MEMORY_ORDER(__m) {
0660 return __o->wait(__v, __m);
0661 }
0662
0663
0664
0665 template <class _Tp>
0666 _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void atomic_notify_one(volatile atomic<_Tp>* __o) _NOEXCEPT {
0667 __o->notify_one();
0668 }
0669 template <class _Tp>
0670 _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void atomic_notify_one(atomic<_Tp>* __o) _NOEXCEPT {
0671 __o->notify_one();
0672 }
0673
0674
0675
0676 template <class _Tp>
0677 _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void atomic_notify_all(volatile atomic<_Tp>* __o) _NOEXCEPT {
0678 __o->notify_all();
0679 }
0680 template <class _Tp>
0681 _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void atomic_notify_all(atomic<_Tp>* __o) _NOEXCEPT {
0682 __o->notify_all();
0683 }
0684
0685 #endif
0686
0687
0688
0689 template <class _Tp>
0690 _LIBCPP_HIDE_FROM_ABI _Tp
0691 atomic_fetch_add(volatile atomic<_Tp>* __o, typename atomic<_Tp>::difference_type __op) _NOEXCEPT {
0692 return __o->fetch_add(__op);
0693 }
0694
0695 template <class _Tp>
0696 _LIBCPP_HIDE_FROM_ABI _Tp atomic_fetch_add(atomic<_Tp>* __o, typename atomic<_Tp>::difference_type __op) _NOEXCEPT {
0697 return __o->fetch_add(__op);
0698 }
0699
0700
0701
0702 template <class _Tp>
0703 _LIBCPP_HIDE_FROM_ABI _Tp atomic_fetch_add_explicit(
0704 volatile atomic<_Tp>* __o, typename atomic<_Tp>::difference_type __op, memory_order __m) _NOEXCEPT {
0705 return __o->fetch_add(__op, __m);
0706 }
0707
0708 template <class _Tp>
0709 _LIBCPP_HIDE_FROM_ABI _Tp
0710 atomic_fetch_add_explicit(atomic<_Tp>* __o, typename atomic<_Tp>::difference_type __op, memory_order __m) _NOEXCEPT {
0711 return __o->fetch_add(__op, __m);
0712 }
0713
0714
0715
0716 template <class _Tp>
0717 _LIBCPP_HIDE_FROM_ABI _Tp
0718 atomic_fetch_sub(volatile atomic<_Tp>* __o, typename atomic<_Tp>::difference_type __op) _NOEXCEPT {
0719 return __o->fetch_sub(__op);
0720 }
0721
0722 template <class _Tp>
0723 _LIBCPP_HIDE_FROM_ABI _Tp atomic_fetch_sub(atomic<_Tp>* __o, typename atomic<_Tp>::difference_type __op) _NOEXCEPT {
0724 return __o->fetch_sub(__op);
0725 }
0726
0727
0728
0729 template <class _Tp>
0730 _LIBCPP_HIDE_FROM_ABI _Tp atomic_fetch_sub_explicit(
0731 volatile atomic<_Tp>* __o, typename atomic<_Tp>::difference_type __op, memory_order __m) _NOEXCEPT {
0732 return __o->fetch_sub(__op, __m);
0733 }
0734
0735 template <class _Tp>
0736 _LIBCPP_HIDE_FROM_ABI _Tp
0737 atomic_fetch_sub_explicit(atomic<_Tp>* __o, typename atomic<_Tp>::difference_type __op, memory_order __m) _NOEXCEPT {
0738 return __o->fetch_sub(__op, __m);
0739 }
0740
0741
0742
0743 template <class _Tp, __enable_if_t<is_integral<_Tp>::value && !is_same<_Tp, bool>::value, int> = 0>
0744 _LIBCPP_HIDE_FROM_ABI _Tp atomic_fetch_and(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type __op) _NOEXCEPT {
0745 return __o->fetch_and(__op);
0746 }
0747
0748 template <class _Tp, __enable_if_t<is_integral<_Tp>::value && !is_same<_Tp, bool>::value, int> = 0>
0749 _LIBCPP_HIDE_FROM_ABI _Tp atomic_fetch_and(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __op) _NOEXCEPT {
0750 return __o->fetch_and(__op);
0751 }
0752
0753
0754
0755 template <class _Tp, __enable_if_t<is_integral<_Tp>::value && !is_same<_Tp, bool>::value, int> = 0>
0756 _LIBCPP_HIDE_FROM_ABI _Tp atomic_fetch_and_explicit(
0757 volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type __op, memory_order __m) _NOEXCEPT {
0758 return __o->fetch_and(__op, __m);
0759 }
0760
0761 template <class _Tp, __enable_if_t<is_integral<_Tp>::value && !is_same<_Tp, bool>::value, int> = 0>
0762 _LIBCPP_HIDE_FROM_ABI _Tp
0763 atomic_fetch_and_explicit(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __op, memory_order __m) _NOEXCEPT {
0764 return __o->fetch_and(__op, __m);
0765 }
0766
0767
0768
0769 template <class _Tp, __enable_if_t<is_integral<_Tp>::value && !is_same<_Tp, bool>::value, int> = 0>
0770 _LIBCPP_HIDE_FROM_ABI _Tp atomic_fetch_or(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type __op) _NOEXCEPT {
0771 return __o->fetch_or(__op);
0772 }
0773
0774 template <class _Tp, __enable_if_t<is_integral<_Tp>::value && !is_same<_Tp, bool>::value, int> = 0>
0775 _LIBCPP_HIDE_FROM_ABI _Tp atomic_fetch_or(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __op) _NOEXCEPT {
0776 return __o->fetch_or(__op);
0777 }
0778
0779
0780
0781 template <class _Tp, __enable_if_t<is_integral<_Tp>::value && !is_same<_Tp, bool>::value, int> = 0>
0782 _LIBCPP_HIDE_FROM_ABI _Tp
0783 atomic_fetch_or_explicit(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type __op, memory_order __m) _NOEXCEPT {
0784 return __o->fetch_or(__op, __m);
0785 }
0786
0787 template <class _Tp, __enable_if_t<is_integral<_Tp>::value && !is_same<_Tp, bool>::value, int> = 0>
0788 _LIBCPP_HIDE_FROM_ABI _Tp
0789 atomic_fetch_or_explicit(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __op, memory_order __m) _NOEXCEPT {
0790 return __o->fetch_or(__op, __m);
0791 }
0792
0793
0794
0795 template <class _Tp, __enable_if_t<is_integral<_Tp>::value && !is_same<_Tp, bool>::value, int> = 0>
0796 _LIBCPP_HIDE_FROM_ABI _Tp atomic_fetch_xor(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type __op) _NOEXCEPT {
0797 return __o->fetch_xor(__op);
0798 }
0799
0800 template <class _Tp, __enable_if_t<is_integral<_Tp>::value && !is_same<_Tp, bool>::value, int> = 0>
0801 _LIBCPP_HIDE_FROM_ABI _Tp atomic_fetch_xor(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __op) _NOEXCEPT {
0802 return __o->fetch_xor(__op);
0803 }
0804
0805
0806
0807 template <class _Tp, __enable_if_t<is_integral<_Tp>::value && !is_same<_Tp, bool>::value, int> = 0>
0808 _LIBCPP_HIDE_FROM_ABI _Tp atomic_fetch_xor_explicit(
0809 volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type __op, memory_order __m) _NOEXCEPT {
0810 return __o->fetch_xor(__op, __m);
0811 }
0812
0813 template <class _Tp, __enable_if_t<is_integral<_Tp>::value && !is_same<_Tp, bool>::value, int> = 0>
0814 _LIBCPP_HIDE_FROM_ABI _Tp
0815 atomic_fetch_xor_explicit(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __op, memory_order __m) _NOEXCEPT {
0816 return __o->fetch_xor(__op, __m);
0817 }
0818
0819 _LIBCPP_END_NAMESPACE_STD
0820
0821 #endif