atomic_support.h revision 292928
1#ifndef ATOMIC_SUPPORT_H 2#define ATOMIC_SUPPORT_H 3 4#include "__config" 5#include "memory" // for __libcpp_relaxed_load 6 7#if defined(__clang__) && __has_builtin(__atomic_load_n) \ 8 && __has_builtin(__atomic_store_n) \ 9 && __has_builtin(__atomic_add_fetch) \ 10 && __has_builtin(__atomic_compare_exchange_n) \ 11 && defined(__ATOMIC_RELAXED) \ 12 && defined(__ATOMIC_CONSUME) \ 13 && defined(__ATOMIC_ACQUIRE) \ 14 && defined(__ATOMIC_RELEASE) \ 15 && defined(__ATOMIC_ACQ_REL) \ 16 && defined(__ATOMIC_SEQ_CST) 17# define _LIBCPP_HAS_ATOMIC_BUILTINS 18#elif !defined(__clang__) && defined(_GNUC_VER) && _GNUC_VER >= 407 19# define _LIBCPP_HAS_ATOMIC_BUILTINS 20#endif 21 22#if !defined(_LIBCPP_HAS_ATOMIC_BUILTINS) && !defined(_LIBCPP_HAS_NO_THREADS) 23# if defined(_MSC_VER) && !defined(__clang__) 24 _LIBCPP_WARNING("Building libc++ without __atomic builtins is unsupported") 25# else 26# warning Building libc++ without __atomic builtins is unsupported 27# endif 28#endif 29 30_LIBCPP_BEGIN_NAMESPACE_STD 31 32namespace { 33 34#if defined(_LIBCPP_HAS_ATOMIC_BUILTINS) && !defined(_LIBCPP_HAS_NO_THREADS) 35 36enum __libcpp_atomic_order { 37 _AO_Relaxed = __ATOMIC_RELAXED, 38 _AO_Consume = __ATOMIC_CONSUME, 39 _AO_Aquire = __ATOMIC_ACQUIRE, 40 _AO_Release = __ATOMIC_RELEASE, 41 _AO_Acq_Rel = __ATOMIC_ACQ_REL, 42 _AO_Seq = __ATOMIC_SEQ_CST 43}; 44 45template <class _ValueType, class _FromType> 46inline _LIBCPP_INLINE_VISIBILITY 47void __libcpp_atomic_store(_ValueType* __dest, _FromType __val, 48 int __order = _AO_Seq) 49{ 50 __atomic_store_n(__dest, __val, __order); 51} 52 53template <class _ValueType, class _FromType> 54inline _LIBCPP_INLINE_VISIBILITY 55void __libcpp_relaxed_store(_ValueType* __dest, _FromType __val) 56{ 57 __atomic_store_n(__dest, __val, _AO_Relaxed); 58} 59 60template <class _ValueType> 61inline _LIBCPP_INLINE_VISIBILITY 62_ValueType __libcpp_atomic_load(_ValueType const* __val, 63 int __order = _AO_Seq) 64{ 65 return __atomic_load_n(__val, __order); 66} 67 68template <class _ValueType, class _AddType> 69inline _LIBCPP_INLINE_VISIBILITY 70_ValueType __libcpp_atomic_add(_ValueType* __val, _AddType __a, 71 int __order = _AO_Seq) 72{ 73 return __atomic_add_fetch(__val, __a, __order); 74} 75 76template <class _ValueType> 77inline _LIBCPP_INLINE_VISIBILITY 78bool __libcpp_atomic_compare_exchange(_ValueType* __val, 79 _ValueType* __expected, _ValueType __after, 80 int __success_order = _AO_Seq, 81 int __fail_order = _AO_Seq) 82{ 83 return __atomic_compare_exchange_n(__val, __expected, __after, true, 84 __success_order, __fail_order); 85} 86 87#else // _LIBCPP_HAS_NO_THREADS 88 89enum __libcpp_atomic_order { 90 _AO_Relaxed, 91 _AO_Consume, 92 _AO_Acquire, 93 _AO_Release, 94 _AO_Acq_Rel, 95 _AO_Seq 96}; 97 98template <class _ValueType, class _FromType> 99inline _LIBCPP_INLINE_VISIBILITY 100void __libcpp_atomic_store(_ValueType* __dest, _FromType __val, 101 int = 0) 102{ 103 *__dest = __val; 104} 105 106template <class _ValueType, class _FromType> 107inline _LIBCPP_INLINE_VISIBILITY 108void __libcpp_relaxed_store(_ValueType* __dest, _FromType __val) 109{ 110 *__dest = __val; 111} 112 113template <class _ValueType> 114inline _LIBCPP_INLINE_VISIBILITY 115_ValueType __libcpp_atomic_load(_ValueType const* __val, 116 int = 0) 117{ 118 return *__val; 119} 120 121template <class _ValueType, class _AddType> 122inline _LIBCPP_INLINE_VISIBILITY 123_ValueType __libcpp_atomic_add(_ValueType* __val, _AddType __a, 124 int = 0) 125{ 126 return *__val += __a; 127} 128 129template <class _ValueType> 130inline _LIBCPP_INLINE_VISIBILITY 131bool __libcpp_atomic_compare_exchange(_ValueType* __val, 132 _ValueType* __expected, _ValueType __after, 133 int = 0, int = 0) 134{ 135 if (*__val == *__expected) { 136 *__val = __after; 137 return true; 138 } 139 *__expected = *__val; 140 return false; 141} 142 143#endif // _LIBCPP_HAS_NO_THREADS 144 145} // end namespace 146 147_LIBCPP_END_NAMESPACE_STD 148 149#endif // ATOMIC_SUPPORT_H 150