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