NIM PC Cross Platform SDK
载入中...
搜索中...
未找到
ne_stl_atomic.h
浏览该文件的文档.
1#ifndef NE_STL_INCLUDENE_STL_ATOMIC_H
2#define NE_STL_INCLUDENE_STL_ATOMIC_H
3
4#include "ne_stl_build.h"
5#if defined(NE_STL_USE_CLANG) || defined(NE_STL_USE_GCC)
6#define NE_STL_ATOMIC_USE_GCC_INTRINSICS
7#elif defined(NE_STL_USE_MSVC)
8#define NE_STL_ATOMIC_USE_MSVC_INTRINSICS
9namespace {
10namespace msvc_atomic {
11template <typename T, std::size_t N = sizeof(T)>
12struct interlocked {};
13
14template <typename T>
15struct interlocked<T, 1> {
16 static inline T increment(T volatile* x) {
17 int8_t old_val, new_val;
18 do {
19 old_val = static_cast<int8_t>(*x);
20 new_val = old_val + static_cast<int8_t>(1);
21 } while (_InterlockedCompareExchange8(reinterpret_cast<volatile int8_t*>(x), new_val, old_val) != old_val);
22 return static_cast<T>(new_val);
23 }
24
25 static inline T decrement(T volatile* x) {
26 int8_t old_val, new_val;
27 do {
28 old_val = static_cast<int8_t>(*x);
29 new_val = old_val - static_cast<int8_t>(1);
30 } while (_InterlockedCompareExchange8(reinterpret_cast<volatile int8_t*>(x), new_val, old_val) != old_val);
31 return static_cast<T>(new_val);
32 }
33
34 static inline T compare_exchange(T volatile* x, const T new_val, const T expected_val) {
35 return static_cast<T>(_InterlockedCompareExchange8(
36 reinterpret_cast<volatile int8_t*>(x), static_cast<const int8_t>(new_val), static_cast<const int8_t>(expected_val)));
37 }
38
39 static inline T exchange(T volatile* x, const T new_val) {
40 return static_cast<T>(_InterlockedExchange8(reinterpret_cast<volatile char*>(x), static_cast<const char>(new_val)));
41 }
42};
43
44template <typename T>
45struct interlocked<T, 2> {
46 static inline T increment(T volatile* x) { return static_cast<T>(_InterlockedIncrement16(reinterpret_cast<volatile int16_t*>(x))); }
47
48 static inline T decrement(T volatile* x) { return static_cast<T>(_InterlockedDecrement16(reinterpret_cast<volatile int16_t*>(x))); }
49
50 static inline T compare_exchange(T volatile* x, const T new_val, const T expected_val) {
51 return static_cast<T>(_InterlockedCompareExchange16(
52 reinterpret_cast<volatile int16_t*>(x), static_cast<const int16_t>(new_val), static_cast<const int16_t>(expected_val)));
53 }
54
55 static inline T exchange(T volatile* x, const T new_val) {
56 return static_cast<T>(_InterlockedExchange16(reinterpret_cast<volatile int16_t*>(x), static_cast<const int16_t>(new_val)));
57 }
58};
59
60template <typename T>
61struct interlocked<T, 4> {
62 static inline T increment(T volatile* x) { return static_cast<T>(_InterlockedIncrement(reinterpret_cast<volatile long*>(x))); }
63
64 static inline T decrement(T volatile* x) { return static_cast<T>(_InterlockedDecrement(reinterpret_cast<volatile long*>(x))); }
65
66 static inline T compare_exchange(T volatile* x, const T new_val, const T expected_val) {
67 return static_cast<T>(_InterlockedCompareExchange(
68 reinterpret_cast<volatile long*>(x), static_cast<const long>(new_val), static_cast<const long>(expected_val)));
69 }
70
71 static inline T exchange(T volatile* x, const T new_val) {
72 long ret = _InterlockedExchange(reinterpret_cast<volatile long*>(x), *((long*)((void*)(&new_val))));
73 return *(T*)((void*)(&ret));
74 }
75};
76
77template <typename T>
78struct interlocked<T, 8> {
79 static inline T increment(T volatile* x) {
80#if defined(NE_STL_ARC_HCPU_64_BITS)
81 return static_cast<T>(_InterlockedIncrement64(reinterpret_cast<volatile int64_t*>(x)));
82#else
83 int64_t old_val, new_val;
84 do {
85 old_val = static_cast<int64_t>(*x);
86 new_val = old_val + static_cast<int64_t>(1);
87 } while (_InterlockedCompareExchange64(reinterpret_cast<volatile int64_t*>(x), new_val, old_val) != old_val);
88 return static_cast<T>(new_val);
89#endif // NE_STL_ARC_HCPU_64_BITS
90 }
91
92 static inline T decrement(T volatile* x) {
93#if defined(NE_STL_ARC_HCPU_64_BITS)
94 return static_cast<T>(_InterlockedDecrement64(reinterpret_cast<volatile int64_t*>(x)));
95#else
96 int64_t old_val, new_val;
97 do {
98 old_val = static_cast<int64_t>(*x);
99 new_val = old_val - static_cast<int64_t>(1);
100 } while (_InterlockedCompareExchange64(reinterpret_cast<volatile int64_t*>(x), new_val, old_val) != old_val);
101 return static_cast<T>(new_val);
102#endif // NE_STL_ARC_HCPU_64_BITS
103 }
104
105 static inline T compare_exchange(T volatile* x, const T new_val, const T expected_val) {
106 return reinterpret_cast<T>(_InterlockedCompareExchange64(
107 reinterpret_cast<volatile int64_t*>(x), reinterpret_cast<const int64_t>(new_val), reinterpret_cast<const int64_t>(expected_val)));
108 }
109
110 static inline T exchange(T volatile* x, const T new_val) {
111#if defined(NE_STL_ARC_HCPU_64_BITS)
112 return reinterpret_cast<T>(_InterlockedExchange64(reinterpret_cast<volatile int64_t*>(x), reinterpret_cast<const int64_t>(new_val)));
113#else
114 int64_t old_val;
115 do {
116 old_val = static_cast<int64_t>(*x);
117 } while (_InterlockedCompareExchange64(reinterpret_cast<volatile int64_t*>(x), new_val, old_val) != old_val);
118 return static_cast<T>(old_val);
119#endif // NE_STL_ARC_HCPU_64_BITS
120 }
121};
122} // namespace msvc_atomic
123} // namespace
124#else
125#error Unsupported compiler / system.
126#endif
127
128namespace nstd {
129
130template <class T>
131class atomic {
132public:
133 static_assert(sizeof(T) == 1 || sizeof(T) == 2 || sizeof(T) == 4 || sizeof(T) == 8, "Only types of size 1, 2, 4 or 8 are supported");
134
136 : value_(static_cast<T>(0)) {}
137
138 explicit atomic(const T value)
139 : value_(value) {}
140
142#if defined(NE_STL_ATOMIC_USE_GCC_INTRINSICS)
143 return __atomic_add_fetch(&value_, 1, __ATOMIC_SEQ_CST);
144#elif defined(NE_STL_ATOMIC_USE_MSVC_INTRINSICS)
145 return msvc_atomic::interlocked<T>::increment(&value_);
146#else
147 return ++value_;
148#endif
149 }
150
152#if defined(NE_STL_ATOMIC_USE_GCC_INTRINSICS)
153 return __atomic_sub_fetch(&value_, 1, __ATOMIC_SEQ_CST);
154#elif defined(NE_STL_ATOMIC_USE_MSVC_INTRINSICS)
155 return msvc_atomic::interlocked<T>::decrement(&value_);
156#else
157 return --value_;
158#endif
159 }
160
161 bool compare_exchange(const T expected_val, const T new_val) {
162#if defined(NE_STL_ATOMIC_USE_GCC_INTRINSICS)
163 T e = expected_val;
164 return __atomic_compare_exchange_n(&value_, &e, new_val, true, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST);
165#elif defined(NE_STL_ATOMIC_USE_MSVC_INTRINSICS)
166 const T old_val = msvc_atomic::interlocked<T>::compare_exchange(&value_, new_val, expected_val);
167 return (old_val == expected_val);
168#else
169 T e = expected_val;
170 return value_.compare_exchange_weak(e, new_val);
171#endif
172 }
173
174 void store(const T new_val) {
175#if defined(NE_STL_ATOMIC_USE_GCC_INTRINSICS)
176 __atomic_store_n(&value_, new_val, __ATOMIC_SEQ_CST);
177#elif defined(NE_STL_ATOMIC_USE_MSVC_INTRINSICS)
178 (void)msvc_atomic::interlocked<T>::exchange(&value_, new_val);
179#else
180 value_.store(new_val);
181#endif
182 }
183
184 T load() const {
185#if defined(NE_STL_ATOMIC_USE_GCC_INTRINSICS)
186 return __atomic_load_n(&value_, __ATOMIC_SEQ_CST);
187#elif defined(NE_STL_ATOMIC_USE_MSVC_INTRINSICS)
188 return value_;
189#else
190 return value_;
191#endif
192 }
193
194 T exchange(const T new_val) {
195#if defined(NE_STL_ATOMIC_USE_GCC_INTRINSICS)
196 return __atomic_exchange_n(&value_, new_val, __ATOMIC_SEQ_CST);
197#elif defined(NE_STL_ATOMIC_USE_MSVC_INTRINSICS)
198 return msvc_atomic::interlocked<T>::exchange(&value_, new_val);
199#else
200 return value_.exchange(new_val);
201#endif
202 }
203
204 T operator=(const T new_value) {
205 store(new_value);
206 return new_value;
207 }
208
209 // operator T() const {
210 // return load();
211 //}
212 operator const T() const { return load(); }
213
214private:
215#if defined(NE_STL_ATOMIC_USE_GCC_INTRINSICS) || defined(NE_STL_ATOMIC_USE_MSVC_INTRINSICS)
216 volatile T value_;
217#else
218 std::atomic<T> value_;
219#endif
220
221 atomic& operator=(const atomic&) = delete;
222};
223
236
237} // namespace nstd
238
239#endif // !NE_STL_INCLUDENE_STL_ATOMIC_H
T exchange(T &obj, U &&new_value)
Definition: phmap_base.h:1127
Definition: ne_stl_any.h:7
nstd::atomic< uint32_t > atomic_ulong
Definition: ne_stl_atomic.h:233
nstd::atomic< int32_t > atomic_int
Definition: ne_stl_atomic.h:230
nstd::atomic< uint64_t > atomic_ullong
Definition: ne_stl_atomic.h:235
nstd::atomic< int32_t > atomic_long
Definition: ne_stl_atomic.h:232
nstd::atomic< bool > atomic_bool
Definition: ne_stl_atomic.h:224
nstd::atomic< int8_t > atomic_schar
Definition: ne_stl_atomic.h:226
nstd::atomic< int64_t > atomic_llong
Definition: ne_stl_atomic.h:234
nstd::atomic< int16_t > atomic_short
Definition: ne_stl_atomic.h:228
nstd::atomic< char > atomic_char
Definition: ne_stl_atomic.h:225
nstd::atomic< uint32_t > atomic_uint
Definition: ne_stl_atomic.h:231
nstd::atomic< uint8_t > atomic_uchar
Definition: ne_stl_atomic.h:227
nstd::atomic< uint16_t > atomic_ushort
Definition: ne_stl_atomic.h:229
Definition: ne_stl_atomic.h:131
std::atomic< T > value_
Definition: ne_stl_atomic.h:218
T load() const
Definition: ne_stl_atomic.h:184
T operator=(const T new_value)
Definition: ne_stl_atomic.h:204
T exchange(const T new_val)
Definition: ne_stl_atomic.h:194
atomic()
Definition: ne_stl_atomic.h:135
atomic & operator=(const atomic &)=delete
T operator--()
Definition: ne_stl_atomic.h:151
bool compare_exchange(const T expected_val, const T new_val)
Definition: ne_stl_atomic.h:161
atomic(const T value)
Definition: ne_stl_atomic.h:138
void store(const T new_val)
Definition: ne_stl_atomic.h:174
T operator++()
Definition: ne_stl_atomic.h:141