Path: blob/main/contrib/llvm-project/libcxx/include/__cxx03/__atomic/atomic.h
213799 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___CXX03___ATOMIC_ATOMIC_H9#define _LIBCPP___CXX03___ATOMIC_ATOMIC_H1011#include <__cxx03/__atomic/atomic_base.h>12#include <__cxx03/__atomic/check_memory_order.h>13#include <__cxx03/__atomic/cxx_atomic_impl.h>14#include <__cxx03/__atomic/memory_order.h>15#include <__cxx03/__config>16#include <__cxx03/__functional/operations.h>17#include <__cxx03/__memory/addressof.h>18#include <__cxx03/__type_traits/is_floating_point.h>19#include <__cxx03/__type_traits/is_function.h>20#include <__cxx03/__type_traits/is_same.h>21#include <__cxx03/__type_traits/remove_const.h>22#include <__cxx03/__type_traits/remove_pointer.h>23#include <__cxx03/__type_traits/remove_volatile.h>24#include <__cxx03/__utility/forward.h>25#include <__cxx03/cstddef>26#include <__cxx03/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_LIBCPP_HIDE_FROM_ABI atomic() _NOEXCEPT = default;4142_LIBCPP_HIDE_FROM_ABI atomic(_Tp __d) _NOEXCEPT : __base(__d) {}4344_LIBCPP_HIDE_FROM_ABI _Tp operator=(_Tp __d) volatile _NOEXCEPT {45__base::store(__d);46return __d;47}48_LIBCPP_HIDE_FROM_ABI _Tp operator=(_Tp __d) _NOEXCEPT {49__base::store(__d);50return __d;51}5253atomic& operator=(const atomic&) = delete;54atomic& operator=(const atomic&) volatile = delete;55};5657// atomic<T*>5859template <class _Tp>60struct atomic<_Tp*> : public __atomic_base<_Tp*> {61using __base = __atomic_base<_Tp*>;62using value_type = _Tp*;63using difference_type = ptrdiff_t;6465_LIBCPP_HIDE_FROM_ABI atomic() _NOEXCEPT = default;6667_LIBCPP_HIDE_FROM_ABI atomic(_Tp* __d) _NOEXCEPT : __base(__d) {}6869_LIBCPP_HIDE_FROM_ABI _Tp* operator=(_Tp* __d) volatile _NOEXCEPT {70__base::store(__d);71return __d;72}73_LIBCPP_HIDE_FROM_ABI _Tp* operator=(_Tp* __d) _NOEXCEPT {74__base::store(__d);75return __d;76}7778_LIBCPP_HIDE_FROM_ABI _Tp* fetch_add(ptrdiff_t __op, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT {79// __atomic_fetch_add accepts function pointers, guard against them.80static_assert(!is_function<__remove_pointer_t<_Tp> >::value, "Pointer to function isn't allowed");81return std::__cxx_atomic_fetch_add(std::addressof(this->__a_), __op, __m);82}8384_LIBCPP_HIDE_FROM_ABI _Tp* fetch_add(ptrdiff_t __op, memory_order __m = memory_order_seq_cst) _NOEXCEPT {85// __atomic_fetch_add accepts function pointers, guard against them.86static_assert(!is_function<__remove_pointer_t<_Tp> >::value, "Pointer to function isn't allowed");87return std::__cxx_atomic_fetch_add(std::addressof(this->__a_), __op, __m);88}8990_LIBCPP_HIDE_FROM_ABI _Tp* fetch_sub(ptrdiff_t __op, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT {91// __atomic_fetch_add accepts function pointers, guard against them.92static_assert(!is_function<__remove_pointer_t<_Tp> >::value, "Pointer to function isn't allowed");93return std::__cxx_atomic_fetch_sub(std::addressof(this->__a_), __op, __m);94}9596_LIBCPP_HIDE_FROM_ABI _Tp* fetch_sub(ptrdiff_t __op, memory_order __m = memory_order_seq_cst) _NOEXCEPT {97// __atomic_fetch_add accepts function pointers, guard against them.98static_assert(!is_function<__remove_pointer_t<_Tp> >::value, "Pointer to function isn't allowed");99return std::__cxx_atomic_fetch_sub(std::addressof(this->__a_), __op, __m);100}101102_LIBCPP_HIDE_FROM_ABI _Tp* operator++(int) volatile _NOEXCEPT { return fetch_add(1); }103_LIBCPP_HIDE_FROM_ABI _Tp* operator++(int) _NOEXCEPT { return fetch_add(1); }104_LIBCPP_HIDE_FROM_ABI _Tp* operator--(int) volatile _NOEXCEPT { return fetch_sub(1); }105_LIBCPP_HIDE_FROM_ABI _Tp* operator--(int) _NOEXCEPT { return fetch_sub(1); }106_LIBCPP_HIDE_FROM_ABI _Tp* operator++() volatile _NOEXCEPT { return fetch_add(1) + 1; }107_LIBCPP_HIDE_FROM_ABI _Tp* operator++() _NOEXCEPT { return fetch_add(1) + 1; }108_LIBCPP_HIDE_FROM_ABI _Tp* operator--() volatile _NOEXCEPT { return fetch_sub(1) - 1; }109_LIBCPP_HIDE_FROM_ABI _Tp* operator--() _NOEXCEPT { return fetch_sub(1) - 1; }110_LIBCPP_HIDE_FROM_ABI _Tp* operator+=(ptrdiff_t __op) volatile _NOEXCEPT { return fetch_add(__op) + __op; }111_LIBCPP_HIDE_FROM_ABI _Tp* operator+=(ptrdiff_t __op) _NOEXCEPT { return fetch_add(__op) + __op; }112_LIBCPP_HIDE_FROM_ABI _Tp* operator-=(ptrdiff_t __op) volatile _NOEXCEPT { return fetch_sub(__op) - __op; }113_LIBCPP_HIDE_FROM_ABI _Tp* operator-=(ptrdiff_t __op) _NOEXCEPT { return fetch_sub(__op) - __op; }114115atomic& operator=(const atomic&) = delete;116atomic& operator=(const atomic&) volatile = delete;117};118119// atomic_is_lock_free120121template <class _Tp>122_LIBCPP_HIDE_FROM_ABI bool atomic_is_lock_free(const volatile atomic<_Tp>* __o) _NOEXCEPT {123return __o->is_lock_free();124}125126template <class _Tp>127_LIBCPP_HIDE_FROM_ABI bool atomic_is_lock_free(const atomic<_Tp>* __o) _NOEXCEPT {128return __o->is_lock_free();129}130131// atomic_init132133template <class _Tp>134_LIBCPP_HIDE_FROM_ABI void atomic_init(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type __d) _NOEXCEPT {135std::__cxx_atomic_init(std::addressof(__o->__a_), __d);136}137138template <class _Tp>139_LIBCPP_HIDE_FROM_ABI void atomic_init(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __d) _NOEXCEPT {140std::__cxx_atomic_init(std::addressof(__o->__a_), __d);141}142143// atomic_store144145template <class _Tp>146_LIBCPP_HIDE_FROM_ABI void atomic_store(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type __d) _NOEXCEPT {147__o->store(__d);148}149150template <class _Tp>151_LIBCPP_HIDE_FROM_ABI void atomic_store(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __d) _NOEXCEPT {152__o->store(__d);153}154155// atomic_store_explicit156157template <class _Tp>158_LIBCPP_HIDE_FROM_ABI void159atomic_store_explicit(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type __d, memory_order __m) _NOEXCEPT160_LIBCPP_CHECK_STORE_MEMORY_ORDER(__m) {161__o->store(__d, __m);162}163164template <class _Tp>165_LIBCPP_HIDE_FROM_ABI void166atomic_store_explicit(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __d, memory_order __m) _NOEXCEPT167_LIBCPP_CHECK_STORE_MEMORY_ORDER(__m) {168__o->store(__d, __m);169}170171// atomic_load172173template <class _Tp>174_LIBCPP_HIDE_FROM_ABI _Tp atomic_load(const volatile atomic<_Tp>* __o) _NOEXCEPT {175return __o->load();176}177178template <class _Tp>179_LIBCPP_HIDE_FROM_ABI _Tp atomic_load(const atomic<_Tp>* __o) _NOEXCEPT {180return __o->load();181}182183// atomic_load_explicit184185template <class _Tp>186_LIBCPP_HIDE_FROM_ABI _Tp atomic_load_explicit(const volatile atomic<_Tp>* __o, memory_order __m) _NOEXCEPT187_LIBCPP_CHECK_LOAD_MEMORY_ORDER(__m) {188return __o->load(__m);189}190191template <class _Tp>192_LIBCPP_HIDE_FROM_ABI _Tp atomic_load_explicit(const atomic<_Tp>* __o, memory_order __m) _NOEXCEPT193_LIBCPP_CHECK_LOAD_MEMORY_ORDER(__m) {194return __o->load(__m);195}196197// atomic_exchange198199template <class _Tp>200_LIBCPP_HIDE_FROM_ABI _Tp atomic_exchange(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type __d) _NOEXCEPT {201return __o->exchange(__d);202}203204template <class _Tp>205_LIBCPP_HIDE_FROM_ABI _Tp atomic_exchange(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __d) _NOEXCEPT {206return __o->exchange(__d);207}208209// atomic_exchange_explicit210211template <class _Tp>212_LIBCPP_HIDE_FROM_ABI _Tp213atomic_exchange_explicit(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type __d, memory_order __m) _NOEXCEPT {214return __o->exchange(__d, __m);215}216217template <class _Tp>218_LIBCPP_HIDE_FROM_ABI _Tp219atomic_exchange_explicit(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __d, memory_order __m) _NOEXCEPT {220return __o->exchange(__d, __m);221}222223// atomic_compare_exchange_weak224225template <class _Tp>226_LIBCPP_HIDE_FROM_ABI bool atomic_compare_exchange_weak(227volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type* __e, typename atomic<_Tp>::value_type __d) _NOEXCEPT {228return __o->compare_exchange_weak(*__e, __d);229}230231template <class _Tp>232_LIBCPP_HIDE_FROM_ABI bool atomic_compare_exchange_weak(233atomic<_Tp>* __o, typename atomic<_Tp>::value_type* __e, typename atomic<_Tp>::value_type __d) _NOEXCEPT {234return __o->compare_exchange_weak(*__e, __d);235}236237// atomic_compare_exchange_strong238239template <class _Tp>240_LIBCPP_HIDE_FROM_ABI bool atomic_compare_exchange_strong(241volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type* __e, typename atomic<_Tp>::value_type __d) _NOEXCEPT {242return __o->compare_exchange_strong(*__e, __d);243}244245template <class _Tp>246_LIBCPP_HIDE_FROM_ABI bool atomic_compare_exchange_strong(247atomic<_Tp>* __o, typename atomic<_Tp>::value_type* __e, typename atomic<_Tp>::value_type __d) _NOEXCEPT {248return __o->compare_exchange_strong(*__e, __d);249}250251// atomic_compare_exchange_weak_explicit252253template <class _Tp>254_LIBCPP_HIDE_FROM_ABI bool atomic_compare_exchange_weak_explicit(255volatile atomic<_Tp>* __o,256typename atomic<_Tp>::value_type* __e,257typename atomic<_Tp>::value_type __d,258memory_order __s,259memory_order __f) _NOEXCEPT _LIBCPP_CHECK_EXCHANGE_MEMORY_ORDER(__s, __f) {260return __o->compare_exchange_weak(*__e, __d, __s, __f);261}262263template <class _Tp>264_LIBCPP_HIDE_FROM_ABI bool atomic_compare_exchange_weak_explicit(265atomic<_Tp>* __o,266typename atomic<_Tp>::value_type* __e,267typename atomic<_Tp>::value_type __d,268memory_order __s,269memory_order __f) _NOEXCEPT _LIBCPP_CHECK_EXCHANGE_MEMORY_ORDER(__s, __f) {270return __o->compare_exchange_weak(*__e, __d, __s, __f);271}272273// atomic_compare_exchange_strong_explicit274275template <class _Tp>276_LIBCPP_HIDE_FROM_ABI bool atomic_compare_exchange_strong_explicit(277volatile atomic<_Tp>* __o,278typename atomic<_Tp>::value_type* __e,279typename atomic<_Tp>::value_type __d,280memory_order __s,281memory_order __f) _NOEXCEPT _LIBCPP_CHECK_EXCHANGE_MEMORY_ORDER(__s, __f) {282return __o->compare_exchange_strong(*__e, __d, __s, __f);283}284285template <class _Tp>286_LIBCPP_HIDE_FROM_ABI bool atomic_compare_exchange_strong_explicit(287atomic<_Tp>* __o,288typename atomic<_Tp>::value_type* __e,289typename atomic<_Tp>::value_type __d,290memory_order __s,291memory_order __f) _NOEXCEPT _LIBCPP_CHECK_EXCHANGE_MEMORY_ORDER(__s, __f) {292return __o->compare_exchange_strong(*__e, __d, __s, __f);293}294295// atomic_wait296297template <class _Tp>298_LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void299atomic_wait(const volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type __v) _NOEXCEPT {300return __o->wait(__v);301}302303template <class _Tp>304_LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void305atomic_wait(const atomic<_Tp>* __o, typename atomic<_Tp>::value_type __v) _NOEXCEPT {306return __o->wait(__v);307}308309// atomic_wait_explicit310311template <class _Tp>312_LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void313atomic_wait_explicit(const volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type __v, memory_order __m) _NOEXCEPT314_LIBCPP_CHECK_LOAD_MEMORY_ORDER(__m) {315return __o->wait(__v, __m);316}317318template <class _Tp>319_LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void320atomic_wait_explicit(const atomic<_Tp>* __o, typename atomic<_Tp>::value_type __v, memory_order __m) _NOEXCEPT321_LIBCPP_CHECK_LOAD_MEMORY_ORDER(__m) {322return __o->wait(__v, __m);323}324325// atomic_notify_one326327template <class _Tp>328_LIBCPP_DEPRECATED_ATOMIC_SYNC _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void329atomic_notify_one(volatile atomic<_Tp>* __o) _NOEXCEPT {330__o->notify_one();331}332template <class _Tp>333_LIBCPP_DEPRECATED_ATOMIC_SYNC _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void334atomic_notify_one(atomic<_Tp>* __o) _NOEXCEPT {335__o->notify_one();336}337338// atomic_notify_all339340template <class _Tp>341_LIBCPP_DEPRECATED_ATOMIC_SYNC _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void342atomic_notify_all(volatile atomic<_Tp>* __o) _NOEXCEPT {343__o->notify_all();344}345template <class _Tp>346_LIBCPP_DEPRECATED_ATOMIC_SYNC _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void347atomic_notify_all(atomic<_Tp>* __o) _NOEXCEPT {348__o->notify_all();349}350351// atomic_fetch_add352353template <class _Tp>354_LIBCPP_HIDE_FROM_ABI _Tp355atomic_fetch_add(volatile atomic<_Tp>* __o, typename atomic<_Tp>::difference_type __op) _NOEXCEPT {356return __o->fetch_add(__op);357}358359template <class _Tp>360_LIBCPP_HIDE_FROM_ABI _Tp atomic_fetch_add(atomic<_Tp>* __o, typename atomic<_Tp>::difference_type __op) _NOEXCEPT {361return __o->fetch_add(__op);362}363364// atomic_fetch_add_explicit365366template <class _Tp>367_LIBCPP_HIDE_FROM_ABI _Tp atomic_fetch_add_explicit(368volatile atomic<_Tp>* __o, typename atomic<_Tp>::difference_type __op, memory_order __m) _NOEXCEPT {369return __o->fetch_add(__op, __m);370}371372template <class _Tp>373_LIBCPP_HIDE_FROM_ABI _Tp374atomic_fetch_add_explicit(atomic<_Tp>* __o, typename atomic<_Tp>::difference_type __op, memory_order __m) _NOEXCEPT {375return __o->fetch_add(__op, __m);376}377378// atomic_fetch_sub379380template <class _Tp>381_LIBCPP_HIDE_FROM_ABI _Tp382atomic_fetch_sub(volatile atomic<_Tp>* __o, typename atomic<_Tp>::difference_type __op) _NOEXCEPT {383return __o->fetch_sub(__op);384}385386template <class _Tp>387_LIBCPP_HIDE_FROM_ABI _Tp atomic_fetch_sub(atomic<_Tp>* __o, typename atomic<_Tp>::difference_type __op) _NOEXCEPT {388return __o->fetch_sub(__op);389}390391// atomic_fetch_sub_explicit392393template <class _Tp>394_LIBCPP_HIDE_FROM_ABI _Tp atomic_fetch_sub_explicit(395volatile atomic<_Tp>* __o, typename atomic<_Tp>::difference_type __op, memory_order __m) _NOEXCEPT {396return __o->fetch_sub(__op, __m);397}398399template <class _Tp>400_LIBCPP_HIDE_FROM_ABI _Tp401atomic_fetch_sub_explicit(atomic<_Tp>* __o, typename atomic<_Tp>::difference_type __op, memory_order __m) _NOEXCEPT {402return __o->fetch_sub(__op, __m);403}404405// atomic_fetch_and406407template <class _Tp, __enable_if_t<is_integral<_Tp>::value && !is_same<_Tp, bool>::value, int> = 0>408_LIBCPP_HIDE_FROM_ABI _Tp atomic_fetch_and(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type __op) _NOEXCEPT {409return __o->fetch_and(__op);410}411412template <class _Tp, __enable_if_t<is_integral<_Tp>::value && !is_same<_Tp, bool>::value, int> = 0>413_LIBCPP_HIDE_FROM_ABI _Tp atomic_fetch_and(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __op) _NOEXCEPT {414return __o->fetch_and(__op);415}416417// atomic_fetch_and_explicit418419template <class _Tp, __enable_if_t<is_integral<_Tp>::value && !is_same<_Tp, bool>::value, int> = 0>420_LIBCPP_HIDE_FROM_ABI _Tp atomic_fetch_and_explicit(421volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type __op, memory_order __m) _NOEXCEPT {422return __o->fetch_and(__op, __m);423}424425template <class _Tp, __enable_if_t<is_integral<_Tp>::value && !is_same<_Tp, bool>::value, int> = 0>426_LIBCPP_HIDE_FROM_ABI _Tp427atomic_fetch_and_explicit(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __op, memory_order __m) _NOEXCEPT {428return __o->fetch_and(__op, __m);429}430431// atomic_fetch_or432433template <class _Tp, __enable_if_t<is_integral<_Tp>::value && !is_same<_Tp, bool>::value, int> = 0>434_LIBCPP_HIDE_FROM_ABI _Tp atomic_fetch_or(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type __op) _NOEXCEPT {435return __o->fetch_or(__op);436}437438template <class _Tp, __enable_if_t<is_integral<_Tp>::value && !is_same<_Tp, bool>::value, int> = 0>439_LIBCPP_HIDE_FROM_ABI _Tp atomic_fetch_or(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __op) _NOEXCEPT {440return __o->fetch_or(__op);441}442443// atomic_fetch_or_explicit444445template <class _Tp, __enable_if_t<is_integral<_Tp>::value && !is_same<_Tp, bool>::value, int> = 0>446_LIBCPP_HIDE_FROM_ABI _Tp447atomic_fetch_or_explicit(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type __op, memory_order __m) _NOEXCEPT {448return __o->fetch_or(__op, __m);449}450451template <class _Tp, __enable_if_t<is_integral<_Tp>::value && !is_same<_Tp, bool>::value, int> = 0>452_LIBCPP_HIDE_FROM_ABI _Tp453atomic_fetch_or_explicit(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __op, memory_order __m) _NOEXCEPT {454return __o->fetch_or(__op, __m);455}456457// atomic_fetch_xor458459template <class _Tp, __enable_if_t<is_integral<_Tp>::value && !is_same<_Tp, bool>::value, int> = 0>460_LIBCPP_HIDE_FROM_ABI _Tp atomic_fetch_xor(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type __op) _NOEXCEPT {461return __o->fetch_xor(__op);462}463464template <class _Tp, __enable_if_t<is_integral<_Tp>::value && !is_same<_Tp, bool>::value, int> = 0>465_LIBCPP_HIDE_FROM_ABI _Tp atomic_fetch_xor(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __op) _NOEXCEPT {466return __o->fetch_xor(__op);467}468469// atomic_fetch_xor_explicit470471template <class _Tp, __enable_if_t<is_integral<_Tp>::value && !is_same<_Tp, bool>::value, int> = 0>472_LIBCPP_HIDE_FROM_ABI _Tp atomic_fetch_xor_explicit(473volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type __op, memory_order __m) _NOEXCEPT {474return __o->fetch_xor(__op, __m);475}476477template <class _Tp, __enable_if_t<is_integral<_Tp>::value && !is_same<_Tp, bool>::value, int> = 0>478_LIBCPP_HIDE_FROM_ABI _Tp479atomic_fetch_xor_explicit(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __op, memory_order __m) _NOEXCEPT {480return __o->fetch_xor(__op, __m);481}482483_LIBCPP_END_NAMESPACE_STD484485#endif // _LIBCPP___CXX03___ATOMIC_ATOMIC_H486487488