61
61
line)[(2 * static_cast<int>(!!(condition))) - 1] _impl_UNUSED
62
62
#endif
63
63
64
-
#if defined(__GNUC__) || defined(__clang__) || defined(__xlc__)
65
-
#define ATOMIC_USE_GCC_INTRINSICS
64
+
#if defined(ATOMIC_USE_SRT_SYNC_MUTEX) && (ATOMIC_USE_SRT_SYNC_MUTEX == 1)
65
+
// NOTE: Defined at the top level.
66
+
#elif defined(__APPLE__) && (__cplusplus >= 201103L)
67
+
// NOTE: Does support c++11 std::atomic, but the compiler may or
68
+
// may not support GCC atomic intrinsics. So go ahead and use the
69
+
// std::atomic implementation.
70
+
#define ATOMIC_USE_CPP11_ATOMIC
71
+
#elif (defined(__clang__) && defined(__clang_major__) && (__clang_major__ > 5)) \
72
+
|| defined(__xlc__)
73
+
// NOTE: Clang <6 does not support GCC __atomic_* intrinsics. I am unsure
74
+
// about Clang6. Since Clang sets __GNUC__ and __GNUC_MINOR__ of this era
75
+
// to <4.5, older Clang will catch the setting below to use the
76
+
// POSIX Mutex Implementation.
77
+
#define ATOMIC_USE_GCC_INTRINSICS
78
+
#elif defined(__GNUC__) \
79
+
&& ( (__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 7)) )
80
+
// NOTE: The __atomic_* family of intrisics were introduced in GCC-4.7.0.
81
+
// NOTE: This follows #if defined(__clang__), because most if, not all,
82
+
// versions of Clang define __GNUC__ and __GNUC_MINOR__ but often define
83
+
// them to 4.4 or an even earlier version. Most of the newish versions
84
+
// of Clang also support GCC Atomic Intrisics even if they set GCC version
85
+
// macros to <4.7.
86
+
#define ATOMIC_USE_GCC_INTRINSICS
87
+
#elif defined(__GNUC__) && !defined(ATOMIC_USE_SRT_SYNC_MUTEX)
88
+
// NOTE: GCC compiler built-ins for atomic operations are pure
89
+
// compiler extensions prior to GCC-4.7 and were grouped into the
90
+
// the __sync_* family of functions. GCC-4.7, both the c++11 and C11
91
+
// standards had been finalized, and GCC updated their built-ins to
92
+
// better reflect the new memory model and the new functions grouped
93
+
// into the __atomic_* family. Also the memory models were defined
94
+
// differently, than in pre 4.7.
95
+
// TODO: PORT to the pre GCC-4.7 __sync_* intrinsics. In the meantime use
96
+
// the POSIX Mutex Implementation.
97
+
#define ATOMIC_USE_SRT_SYNC_MUTEX 1
66
98
#elif defined(_MSC_VER)
67
-
#define ATOMIC_USE_MSVC_INTRINSICS
68
-
#include "atomic_msvc.h"
99
+
#define ATOMIC_USE_MSVC_INTRINSICS
100
+
#include "atomic_msvc.h"
69
101
#elif __cplusplus >= 201103L
70
-
#define ATOMIC_USE_CPP11_ATOMIC
71
-
#include <atomic>
102
+
#define ATOMIC_USE_CPP11_ATOMIC
72
103
#else
73
-
#error Unsupported compiler / system.
104
+
#error Unsupported compiler / system.
105
+
#endif
106
+
// Include any necessary headers for the selected Atomic Implementation.
107
+
#if defined(ATOMIC_USE_SRT_SYNC_MUTEX) && (ATOMIC_USE_SRT_SYNC_MUTEX == 1)
108
+
#include "sync.h"
109
+
#endif
110
+
#if defined(ATOMIC_USE_CPP11_ATOMIC)
111
+
#include <atomic>
74
112
#endif
75
113
76
114
namespace srt {
@@ -82,31 +120,62 @@ class atomic {
82
120
sizeof(T) == 8,
83
121
"Only types of size 1, 2, 4 or 8 are supported");
84
122
85
-
atomic() : value_(static_cast<T>(0)) {}
123
+
atomic()
124
+
: value_(static_cast<T>(0))
125
+
#if defined(ATOMIC_USE_SRT_SYNC_MUTEX) && (ATOMIC_USE_SRT_SYNC_MUTEX == 1)
126
+
, mutex_()
127
+
#endif
128
+
{
129
+
// No-Op
130
+
}
131
+
132
+
explicit atomic(const T value)
133
+
: value_(value)
134
+
#if defined(ATOMIC_USE_SRT_SYNC_MUTEX) && (ATOMIC_USE_SRT_SYNC_MUTEX == 1)
135
+
, mutex_()
136
+
#endif
137
+
{
138
+
// No-Op
139
+
}
86
140
87
-
explicit atomic(const T value) : value_(value) {}
141
+
~atomic()
142
+
{
143
+
// No-Op
144
+
}
88
145
89
146
/// @brief Performs an atomic increment operation (value + 1).
90
147
/// @returns The new value of the atomic object.
91
148
T operator++() {
92
-
#if defined(ATOMIC_USE_GCC_INTRINSICS)
149
+
#if defined(ATOMIC_USE_SRT_SYNC_MUTEX) && (ATOMIC_USE_SRT_SYNC_MUTEX == 1)
150
+
ScopedLock lg_(mutex_);
151
+
const T t = ++value_;
152
+
return t;
153
+
#elif defined(ATOMIC_USE_GCC_INTRINSICS)
93
154
return __atomic_add_fetch(&value_, 1, __ATOMIC_SEQ_CST);
94
155
#elif defined(ATOMIC_USE_MSVC_INTRINSICS)
95
156
return msvc::interlocked<T>::increment(&value_);
96
-
#else
157
+
#elif defined(ATOMIC_USE_CPP11_ATOMIC)
97
158
return ++value_;
159
+
#else
160
+
#error "Implement Me."
98
161
#endif
99
162
}
100
163
101
164
/// @brief Performs an atomic decrement operation (value - 1).
102
165
/// @returns The new value of the atomic object.
103
166
T operator--() {
104
-
#if defined(ATOMIC_USE_GCC_INTRINSICS)
167
+
#if defined(ATOMIC_USE_SRT_SYNC_MUTEX) && (ATOMIC_USE_SRT_SYNC_MUTEX == 1)
168
+
ScopedLock lg_(mutex_);
169
+
const T t = --value_;
170
+
return t;
171
+
#elif defined(ATOMIC_USE_GCC_INTRINSICS)
105
172
return __atomic_sub_fetch(&value_, 1, __ATOMIC_SEQ_CST);
106
173
#elif defined(ATOMIC_USE_MSVC_INTRINSICS)
107
174
return msvc::interlocked<T>::decrement(&value_);
108
-
#else
175
+
#elif defined(ATOMIC_USE_CPP11_ATOMIC)
109
176
return --value_;
177
+
#else
178
+
#error "Implement Me."
110
179
#endif
111
180
}
112
181
@@ -119,17 +188,28 @@ class atomic {
119
188
/// @param new_val The new value to write to the atomic object.
120
189
/// @returns True if new_value was written to the atomic object.
121
190
bool compare_exchange(const T expected_val, const T new_val) {
122
-
#if defined(ATOMIC_USE_GCC_INTRINSICS)
191
+
#if defined(ATOMIC_USE_SRT_SYNC_MUTEX) && (ATOMIC_USE_SRT_SYNC_MUTEX == 1)
192
+
ScopedLock lg_(mutex_);
193
+
bool result = false;
194
+
if (expected_val == value_)
195
+
{
196
+
value_ = new_val;
197
+
result = true;
198
+
}
199
+
return result;
200
+
#elif defined(ATOMIC_USE_GCC_INTRINSICS)
123
201
T e = expected_val;
124
202
return __atomic_compare_exchange_n(
125
203
&value_, &e, new_val, true, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST);
126
204
#elif defined(ATOMIC_USE_MSVC_INTRINSICS)
127
205
const T old_val =
128
206
msvc::interlocked<T>::compare_exchange(&value_, new_val, expected_val);
129
207
return (old_val == expected_val);
130
-
#else
208
+
#elif defined(ATOMIC_USE_CPP11_ATOMIC)
131
209
T e = expected_val;
132
210
return value_.compare_exchange_weak(e, new_val);
211
+
#else
212
+
#error "Implement Me."
133
213
#endif
134
214
}
135
215
@@ -140,26 +220,37 @@ class atomic {
140
220
///
141
221
/// @param new_val The new value to write to the atomic object.
142
222
void store(const T new_val) {
143
-
#if defined(ATOMIC_USE_GCC_INTRINSICS)
223
+
#if defined(ATOMIC_USE_SRT_SYNC_MUTEX) && (ATOMIC_USE_SRT_SYNC_MUTEX == 1)
224
+
ScopedLock lg_(mutex_);
225
+
value_ = new_val;
226
+
#elif defined(ATOMIC_USE_GCC_INTRINSICS)
144
227
__atomic_store_n(&value_, new_val, __ATOMIC_SEQ_CST);
145
228
#elif defined(ATOMIC_USE_MSVC_INTRINSICS)
146
229
(void)msvc::interlocked<T>::exchange(&value_, new_val);
147
-
#else
230
+
#elif defined(ATOMIC_USE_CPP11_ATOMIC)
148
231
value_.store(new_val);
232
+
#else
233
+
#error "Implement Me."
149
234
#endif
150
235
}
151
236
152
237
/// @returns the current value of the atomic object.
153
238
/// @note Be careful about how this is used, since any operations on the
154
239
/// returned value are inherently non-atomic.
155
240
T load() const {
156
-
#if defined(ATOMIC_USE_GCC_INTRINSICS)
241
+
#if defined(ATOMIC_USE_SRT_SYNC_MUTEX) && (ATOMIC_USE_SRT_SYNC_MUTEX == 1)
242
+
ScopedLock lg_(mutex_);
243
+
const T t = value_;
244
+
return t;
245
+
#elif defined(ATOMIC_USE_GCC_INTRINSICS)
157
246
return __atomic_load_n(&value_, __ATOMIC_SEQ_CST);
158
247
#elif defined(ATOMIC_USE_MSVC_INTRINSICS)
159
248
// TODO(m): Is there a better solution for MSVC?
160
249
return value_;
161
-
#else
250
+
#elif defined(ATOMIC_USE_CPP11_ATOMIC)
162
251
return value_;
252
+
#else
253
+
#error "Implement Me."
163
254
#endif
164
255
}
165
256
@@ -171,12 +262,19 @@ class atomic {
171
262
/// @param new_val The new value to write to the atomic object.
172
263
/// @returns the old value.
173
264
T exchange(const T new_val) {
174
-
#if defined(ATOMIC_USE_GCC_INTRINSICS)
265
+
#if defined(ATOMIC_USE_SRT_SYNC_MUTEX) && (ATOMIC_USE_SRT_SYNC_MUTEX == 1)
266
+
ScopedLock lg_(mutex_);
267
+
const T t = value_;
268
+
value_ = new_val;
269
+
return t;
270
+
#elif defined(ATOMIC_USE_GCC_INTRINSICS)
175
271
return __atomic_exchange_n(&value_, new_val, __ATOMIC_SEQ_CST);
176
272
#elif defined(ATOMIC_USE_MSVC_INTRINSICS)
177
273
return msvc::interlocked<T>::exchange(&value_, new_val);
178
-
#else
274
+
#elif defined(ATOMIC_USE_CPP11_ATOMIC)
179
275
return value_.exchange(new_val);
276
+
#else
277
+
#error "Implement Me."
180
278
#endif
181
279
}
182
280
@@ -190,10 +288,17 @@ class atomic {
190
288
}
191
289
192
290
private:
193
-
#if defined(ATOMIC_USE_GCC_INTRINSICS) || defined(ATOMIC_USE_MSVC_INTRINSICS)
291
+
#if defined(ATOMIC_USE_SRT_SYNC_MUTEX) && (ATOMIC_USE_SRT_SYNC_MUTEX == 1)
292
+
T value_;
293
+
mutable Mutex mutex_;
294
+
#elif defined(ATOMIC_USE_GCC_INTRINSICS)
194
295
volatile T value_;
195
-
#else
296
+
#elif defined(ATOMIC_USE_MSVC_INTRINSICS)
297
+
volatile T value_;
298
+
#elif defined(ATOMIC_USE_CPP11_ATOMIC)
196
299
std::atomic<T> value_;
300
+
#else
301
+
#error "Implement Me. (value_ type)"
197
302
#endif
198
303
199
304
ATOMIC_DISALLOW_COPY(atomic)
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4