485 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_H10#define _LIBCPP___CXX03___ATOMIC_ATOMIC_H11 12#include <__cxx03/__atomic/atomic_base.h>13#include <__cxx03/__atomic/check_memory_order.h>14#include <__cxx03/__atomic/cxx_atomic_impl.h>15#include <__cxx03/__atomic/memory_order.h>16#include <__cxx03/__config>17#include <__cxx03/__functional/operations.h>18#include <__cxx03/__memory/addressof.h>19#include <__cxx03/__type_traits/is_floating_point.h>20#include <__cxx03/__type_traits/is_function.h>21#include <__cxx03/__type_traits/is_same.h>22#include <__cxx03/__type_traits/remove_const.h>23#include <__cxx03/__type_traits/remove_pointer.h>24#include <__cxx03/__type_traits/remove_volatile.h>25#include <__cxx03/__utility/forward.h>26#include <__cxx03/cstddef>27#include <__cxx03/cstring>28 29#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)30# pragma GCC system_header31#endif32 33_LIBCPP_BEGIN_NAMESPACE_STD34 35template <class _Tp>36struct atomic : public __atomic_base<_Tp> {37 using __base = __atomic_base<_Tp>;38 39 _LIBCPP_HIDE_FROM_ABI atomic() _NOEXCEPT = default;40 41 _LIBCPP_HIDE_FROM_ABI atomic(_Tp __d) _NOEXCEPT : __base(__d) {}42 43 _LIBCPP_HIDE_FROM_ABI _Tp operator=(_Tp __d) volatile _NOEXCEPT {44 __base::store(__d);45 return __d;46 }47 _LIBCPP_HIDE_FROM_ABI _Tp operator=(_Tp __d) _NOEXCEPT {48 __base::store(__d);49 return __d;50 }51 52 atomic& operator=(const atomic&) = delete;53 atomic& operator=(const atomic&) volatile = delete;54};55 56// atomic<T*>57 58template <class _Tp>59struct atomic<_Tp*> : public __atomic_base<_Tp*> {60 using __base = __atomic_base<_Tp*>;61 62 using difference_type = ptrdiff_t;63 64 _LIBCPP_HIDE_FROM_ABI atomic() _NOEXCEPT = default;65 66 _LIBCPP_HIDE_FROM_ABI atomic(_Tp* __d) _NOEXCEPT : __base(__d) {}67 68 _LIBCPP_HIDE_FROM_ABI _Tp* operator=(_Tp* __d) volatile _NOEXCEPT {69 __base::store(__d);70 return __d;71 }72 _LIBCPP_HIDE_FROM_ABI _Tp* operator=(_Tp* __d) _NOEXCEPT {73 __base::store(__d);74 return __d;75 }76 77 _LIBCPP_HIDE_FROM_ABI _Tp* fetch_add(ptrdiff_t __op, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT {78 // __atomic_fetch_add accepts function pointers, guard against them.79 static_assert(!is_function<__remove_pointer_t<_Tp> >::value, "Pointer to function isn't allowed");80 return std::__cxx_atomic_fetch_add(std::addressof(this->__a_), __op, __m);81 }82 83 _LIBCPP_HIDE_FROM_ABI _Tp* fetch_add(ptrdiff_t __op, memory_order __m = memory_order_seq_cst) _NOEXCEPT {84 // __atomic_fetch_add accepts function pointers, guard against them.85 static_assert(!is_function<__remove_pointer_t<_Tp> >::value, "Pointer to function isn't allowed");86 return std::__cxx_atomic_fetch_add(std::addressof(this->__a_), __op, __m);87 }88 89 _LIBCPP_HIDE_FROM_ABI _Tp* fetch_sub(ptrdiff_t __op, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT {90 // __atomic_fetch_add accepts function pointers, guard against them.91 static_assert(!is_function<__remove_pointer_t<_Tp> >::value, "Pointer to function isn't allowed");92 return std::__cxx_atomic_fetch_sub(std::addressof(this->__a_), __op, __m);93 }94 95 _LIBCPP_HIDE_FROM_ABI _Tp* fetch_sub(ptrdiff_t __op, memory_order __m = memory_order_seq_cst) _NOEXCEPT {96 // __atomic_fetch_add accepts function pointers, guard against them.97 static_assert(!is_function<__remove_pointer_t<_Tp> >::value, "Pointer to function isn't allowed");98 return std::__cxx_atomic_fetch_sub(std::addressof(this->__a_), __op, __m);99 }100 101 _LIBCPP_HIDE_FROM_ABI _Tp* operator++(int) volatile _NOEXCEPT { return fetch_add(1); }102 _LIBCPP_HIDE_FROM_ABI _Tp* operator++(int) _NOEXCEPT { return fetch_add(1); }103 _LIBCPP_HIDE_FROM_ABI _Tp* operator--(int) volatile _NOEXCEPT { return fetch_sub(1); }104 _LIBCPP_HIDE_FROM_ABI _Tp* operator--(int) _NOEXCEPT { return fetch_sub(1); }105 _LIBCPP_HIDE_FROM_ABI _Tp* operator++() volatile _NOEXCEPT { return fetch_add(1) + 1; }106 _LIBCPP_HIDE_FROM_ABI _Tp* operator++() _NOEXCEPT { return fetch_add(1) + 1; }107 _LIBCPP_HIDE_FROM_ABI _Tp* operator--() volatile _NOEXCEPT { return fetch_sub(1) - 1; }108 _LIBCPP_HIDE_FROM_ABI _Tp* operator--() _NOEXCEPT { return fetch_sub(1) - 1; }109 _LIBCPP_HIDE_FROM_ABI _Tp* operator+=(ptrdiff_t __op) volatile _NOEXCEPT { return fetch_add(__op) + __op; }110 _LIBCPP_HIDE_FROM_ABI _Tp* operator+=(ptrdiff_t __op) _NOEXCEPT { return fetch_add(__op) + __op; }111 _LIBCPP_HIDE_FROM_ABI _Tp* operator-=(ptrdiff_t __op) volatile _NOEXCEPT { return fetch_sub(__op) - __op; }112 _LIBCPP_HIDE_FROM_ABI _Tp* operator-=(ptrdiff_t __op) _NOEXCEPT { return fetch_sub(__op) - __op; }113 114 atomic& operator=(const atomic&) = delete;115 atomic& operator=(const atomic&) volatile = delete;116};117 118// atomic_is_lock_free119 120template <class _Tp>121_LIBCPP_HIDE_FROM_ABI bool atomic_is_lock_free(const volatile atomic<_Tp>* __o) _NOEXCEPT {122 return __o->is_lock_free();123}124 125template <class _Tp>126_LIBCPP_HIDE_FROM_ABI bool atomic_is_lock_free(const atomic<_Tp>* __o) _NOEXCEPT {127 return __o->is_lock_free();128}129 130// atomic_init131 132template <class _Tp>133_LIBCPP_HIDE_FROM_ABI void atomic_init(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type __d) _NOEXCEPT {134 std::__cxx_atomic_init(std::addressof(__o->__a_), __d);135}136 137template <class _Tp>138_LIBCPP_HIDE_FROM_ABI void atomic_init(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __d) _NOEXCEPT {139 std::__cxx_atomic_init(std::addressof(__o->__a_), __d);140}141 142// atomic_store143 144template <class _Tp>145_LIBCPP_HIDE_FROM_ABI void atomic_store(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type __d) _NOEXCEPT {146 __o->store(__d);147}148 149template <class _Tp>150_LIBCPP_HIDE_FROM_ABI void atomic_store(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __d) _NOEXCEPT {151 __o->store(__d);152}153 154// atomic_store_explicit155 156template <class _Tp>157_LIBCPP_HIDE_FROM_ABI void158atomic_store_explicit(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type __d, memory_order __m) _NOEXCEPT159 _LIBCPP_CHECK_STORE_MEMORY_ORDER(__m) {160 __o->store(__d, __m);161}162 163template <class _Tp>164_LIBCPP_HIDE_FROM_ABI void165atomic_store_explicit(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __d, memory_order __m) _NOEXCEPT166 _LIBCPP_CHECK_STORE_MEMORY_ORDER(__m) {167 __o->store(__d, __m);168}169 170// atomic_load171 172template <class _Tp>173_LIBCPP_HIDE_FROM_ABI _Tp atomic_load(const volatile atomic<_Tp>* __o) _NOEXCEPT {174 return __o->load();175}176 177template <class _Tp>178_LIBCPP_HIDE_FROM_ABI _Tp atomic_load(const atomic<_Tp>* __o) _NOEXCEPT {179 return __o->load();180}181 182// atomic_load_explicit183 184template <class _Tp>185_LIBCPP_HIDE_FROM_ABI _Tp atomic_load_explicit(const volatile atomic<_Tp>* __o, memory_order __m) _NOEXCEPT186 _LIBCPP_CHECK_LOAD_MEMORY_ORDER(__m) {187 return __o->load(__m);188}189 190template <class _Tp>191_LIBCPP_HIDE_FROM_ABI _Tp atomic_load_explicit(const atomic<_Tp>* __o, memory_order __m) _NOEXCEPT192 _LIBCPP_CHECK_LOAD_MEMORY_ORDER(__m) {193 return __o->load(__m);194}195 196// atomic_exchange197 198template <class _Tp>199_LIBCPP_HIDE_FROM_ABI _Tp atomic_exchange(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type __d) _NOEXCEPT {200 return __o->exchange(__d);201}202 203template <class _Tp>204_LIBCPP_HIDE_FROM_ABI _Tp atomic_exchange(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __d) _NOEXCEPT {205 return __o->exchange(__d);206}207 208// atomic_exchange_explicit209 210template <class _Tp>211_LIBCPP_HIDE_FROM_ABI _Tp212atomic_exchange_explicit(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type __d, memory_order __m) _NOEXCEPT {213 return __o->exchange(__d, __m);214}215 216template <class _Tp>217_LIBCPP_HIDE_FROM_ABI _Tp218atomic_exchange_explicit(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __d, memory_order __m) _NOEXCEPT {219 return __o->exchange(__d, __m);220}221 222// atomic_compare_exchange_weak223 224template <class _Tp>225_LIBCPP_HIDE_FROM_ABI bool atomic_compare_exchange_weak(226 volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type* __e, typename atomic<_Tp>::value_type __d) _NOEXCEPT {227 return __o->compare_exchange_weak(*__e, __d);228}229 230template <class _Tp>231_LIBCPP_HIDE_FROM_ABI bool atomic_compare_exchange_weak(232 atomic<_Tp>* __o, typename atomic<_Tp>::value_type* __e, typename atomic<_Tp>::value_type __d) _NOEXCEPT {233 return __o->compare_exchange_weak(*__e, __d);234}235 236// atomic_compare_exchange_strong237 238template <class _Tp>239_LIBCPP_HIDE_FROM_ABI bool atomic_compare_exchange_strong(240 volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type* __e, typename atomic<_Tp>::value_type __d) _NOEXCEPT {241 return __o->compare_exchange_strong(*__e, __d);242}243 244template <class _Tp>245_LIBCPP_HIDE_FROM_ABI bool atomic_compare_exchange_strong(246 atomic<_Tp>* __o, typename atomic<_Tp>::value_type* __e, typename atomic<_Tp>::value_type __d) _NOEXCEPT {247 return __o->compare_exchange_strong(*__e, __d);248}249 250// atomic_compare_exchange_weak_explicit251 252template <class _Tp>253_LIBCPP_HIDE_FROM_ABI bool atomic_compare_exchange_weak_explicit(254 volatile atomic<_Tp>* __o,255 typename atomic<_Tp>::value_type* __e,256 typename atomic<_Tp>::value_type __d,257 memory_order __s,258 memory_order __f) _NOEXCEPT _LIBCPP_CHECK_EXCHANGE_MEMORY_ORDER(__s, __f) {259 return __o->compare_exchange_weak(*__e, __d, __s, __f);260}261 262template <class _Tp>263_LIBCPP_HIDE_FROM_ABI bool atomic_compare_exchange_weak_explicit(264 atomic<_Tp>* __o,265 typename atomic<_Tp>::value_type* __e,266 typename atomic<_Tp>::value_type __d,267 memory_order __s,268 memory_order __f) _NOEXCEPT _LIBCPP_CHECK_EXCHANGE_MEMORY_ORDER(__s, __f) {269 return __o->compare_exchange_weak(*__e, __d, __s, __f);270}271 272// atomic_compare_exchange_strong_explicit273 274template <class _Tp>275_LIBCPP_HIDE_FROM_ABI bool atomic_compare_exchange_strong_explicit(276 volatile atomic<_Tp>* __o,277 typename atomic<_Tp>::value_type* __e,278 typename atomic<_Tp>::value_type __d,279 memory_order __s,280 memory_order __f) _NOEXCEPT _LIBCPP_CHECK_EXCHANGE_MEMORY_ORDER(__s, __f) {281 return __o->compare_exchange_strong(*__e, __d, __s, __f);282}283 284template <class _Tp>285_LIBCPP_HIDE_FROM_ABI bool atomic_compare_exchange_strong_explicit(286 atomic<_Tp>* __o,287 typename atomic<_Tp>::value_type* __e,288 typename atomic<_Tp>::value_type __d,289 memory_order __s,290 memory_order __f) _NOEXCEPT _LIBCPP_CHECK_EXCHANGE_MEMORY_ORDER(__s, __f) {291 return __o->compare_exchange_strong(*__e, __d, __s, __f);292}293 294// atomic_wait295 296template <class _Tp>297_LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void298atomic_wait(const volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type __v) _NOEXCEPT {299 return __o->wait(__v);300}301 302template <class _Tp>303_LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void304atomic_wait(const atomic<_Tp>* __o, typename atomic<_Tp>::value_type __v) _NOEXCEPT {305 return __o->wait(__v);306}307 308// atomic_wait_explicit309 310template <class _Tp>311_LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void312atomic_wait_explicit(const volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type __v, memory_order __m) _NOEXCEPT313 _LIBCPP_CHECK_LOAD_MEMORY_ORDER(__m) {314 return __o->wait(__v, __m);315}316 317template <class _Tp>318_LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void319atomic_wait_explicit(const atomic<_Tp>* __o, typename atomic<_Tp>::value_type __v, memory_order __m) _NOEXCEPT320 _LIBCPP_CHECK_LOAD_MEMORY_ORDER(__m) {321 return __o->wait(__v, __m);322}323 324// atomic_notify_one325 326template <class _Tp>327_LIBCPP_DEPRECATED_ATOMIC_SYNC _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void328atomic_notify_one(volatile atomic<_Tp>* __o) _NOEXCEPT {329 __o->notify_one();330}331template <class _Tp>332_LIBCPP_DEPRECATED_ATOMIC_SYNC _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void333atomic_notify_one(atomic<_Tp>* __o) _NOEXCEPT {334 __o->notify_one();335}336 337// atomic_notify_all338 339template <class _Tp>340_LIBCPP_DEPRECATED_ATOMIC_SYNC _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void341atomic_notify_all(volatile atomic<_Tp>* __o) _NOEXCEPT {342 __o->notify_all();343}344template <class _Tp>345_LIBCPP_DEPRECATED_ATOMIC_SYNC _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void346atomic_notify_all(atomic<_Tp>* __o) _NOEXCEPT {347 __o->notify_all();348}349 350// atomic_fetch_add351 352template <class _Tp>353_LIBCPP_HIDE_FROM_ABI _Tp354atomic_fetch_add(volatile atomic<_Tp>* __o, typename atomic<_Tp>::difference_type __op) _NOEXCEPT {355 return __o->fetch_add(__op);356}357 358template <class _Tp>359_LIBCPP_HIDE_FROM_ABI _Tp atomic_fetch_add(atomic<_Tp>* __o, typename atomic<_Tp>::difference_type __op) _NOEXCEPT {360 return __o->fetch_add(__op);361}362 363// atomic_fetch_add_explicit364 365template <class _Tp>366_LIBCPP_HIDE_FROM_ABI _Tp atomic_fetch_add_explicit(367 volatile atomic<_Tp>* __o, typename atomic<_Tp>::difference_type __op, memory_order __m) _NOEXCEPT {368 return __o->fetch_add(__op, __m);369}370 371template <class _Tp>372_LIBCPP_HIDE_FROM_ABI _Tp373atomic_fetch_add_explicit(atomic<_Tp>* __o, typename atomic<_Tp>::difference_type __op, memory_order __m) _NOEXCEPT {374 return __o->fetch_add(__op, __m);375}376 377// atomic_fetch_sub378 379template <class _Tp>380_LIBCPP_HIDE_FROM_ABI _Tp381atomic_fetch_sub(volatile atomic<_Tp>* __o, typename atomic<_Tp>::difference_type __op) _NOEXCEPT {382 return __o->fetch_sub(__op);383}384 385template <class _Tp>386_LIBCPP_HIDE_FROM_ABI _Tp atomic_fetch_sub(atomic<_Tp>* __o, typename atomic<_Tp>::difference_type __op) _NOEXCEPT {387 return __o->fetch_sub(__op);388}389 390// atomic_fetch_sub_explicit391 392template <class _Tp>393_LIBCPP_HIDE_FROM_ABI _Tp atomic_fetch_sub_explicit(394 volatile atomic<_Tp>* __o, typename atomic<_Tp>::difference_type __op, memory_order __m) _NOEXCEPT {395 return __o->fetch_sub(__op, __m);396}397 398template <class _Tp>399_LIBCPP_HIDE_FROM_ABI _Tp400atomic_fetch_sub_explicit(atomic<_Tp>* __o, typename atomic<_Tp>::difference_type __op, memory_order __m) _NOEXCEPT {401 return __o->fetch_sub(__op, __m);402}403 404// atomic_fetch_and405 406template <class _Tp, __enable_if_t<is_integral<_Tp>::value && !is_same<_Tp, bool>::value, int> = 0>407_LIBCPP_HIDE_FROM_ABI _Tp atomic_fetch_and(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type __op) _NOEXCEPT {408 return __o->fetch_and(__op);409}410 411template <class _Tp, __enable_if_t<is_integral<_Tp>::value && !is_same<_Tp, bool>::value, int> = 0>412_LIBCPP_HIDE_FROM_ABI _Tp atomic_fetch_and(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __op) _NOEXCEPT {413 return __o->fetch_and(__op);414}415 416// atomic_fetch_and_explicit417 418template <class _Tp, __enable_if_t<is_integral<_Tp>::value && !is_same<_Tp, bool>::value, int> = 0>419_LIBCPP_HIDE_FROM_ABI _Tp atomic_fetch_and_explicit(420 volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type __op, memory_order __m) _NOEXCEPT {421 return __o->fetch_and(__op, __m);422}423 424template <class _Tp, __enable_if_t<is_integral<_Tp>::value && !is_same<_Tp, bool>::value, int> = 0>425_LIBCPP_HIDE_FROM_ABI _Tp426atomic_fetch_and_explicit(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __op, memory_order __m) _NOEXCEPT {427 return __o->fetch_and(__op, __m);428}429 430// atomic_fetch_or431 432template <class _Tp, __enable_if_t<is_integral<_Tp>::value && !is_same<_Tp, bool>::value, int> = 0>433_LIBCPP_HIDE_FROM_ABI _Tp atomic_fetch_or(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type __op) _NOEXCEPT {434 return __o->fetch_or(__op);435}436 437template <class _Tp, __enable_if_t<is_integral<_Tp>::value && !is_same<_Tp, bool>::value, int> = 0>438_LIBCPP_HIDE_FROM_ABI _Tp atomic_fetch_or(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __op) _NOEXCEPT {439 return __o->fetch_or(__op);440}441 442// atomic_fetch_or_explicit443 444template <class _Tp, __enable_if_t<is_integral<_Tp>::value && !is_same<_Tp, bool>::value, int> = 0>445_LIBCPP_HIDE_FROM_ABI _Tp446atomic_fetch_or_explicit(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type __op, memory_order __m) _NOEXCEPT {447 return __o->fetch_or(__op, __m);448}449 450template <class _Tp, __enable_if_t<is_integral<_Tp>::value && !is_same<_Tp, bool>::value, int> = 0>451_LIBCPP_HIDE_FROM_ABI _Tp452atomic_fetch_or_explicit(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __op, memory_order __m) _NOEXCEPT {453 return __o->fetch_or(__op, __m);454}455 456// atomic_fetch_xor457 458template <class _Tp, __enable_if_t<is_integral<_Tp>::value && !is_same<_Tp, bool>::value, int> = 0>459_LIBCPP_HIDE_FROM_ABI _Tp atomic_fetch_xor(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type __op) _NOEXCEPT {460 return __o->fetch_xor(__op);461}462 463template <class _Tp, __enable_if_t<is_integral<_Tp>::value && !is_same<_Tp, bool>::value, int> = 0>464_LIBCPP_HIDE_FROM_ABI _Tp atomic_fetch_xor(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __op) _NOEXCEPT {465 return __o->fetch_xor(__op);466}467 468// atomic_fetch_xor_explicit469 470template <class _Tp, __enable_if_t<is_integral<_Tp>::value && !is_same<_Tp, bool>::value, int> = 0>471_LIBCPP_HIDE_FROM_ABI _Tp atomic_fetch_xor_explicit(472 volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type __op, memory_order __m) _NOEXCEPT {473 return __o->fetch_xor(__op, __m);474}475 476template <class _Tp, __enable_if_t<is_integral<_Tp>::value && !is_same<_Tp, bool>::value, int> = 0>477_LIBCPP_HIDE_FROM_ABI _Tp478atomic_fetch_xor_explicit(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __op, memory_order __m) _NOEXCEPT {479 return __o->fetch_xor(__op, __m);480}481 482_LIBCPP_END_NAMESPACE_STD483 484#endif // _LIBCPP___CXX03___ATOMIC_ATOMIC_H485