1 | /**************************************************************************** |
2 | ** |
3 | ** Copyright (C) 2011 Thiago Macieira <thiago@kde.org> |
4 | ** Copyright (C) 2016 Intel Corporation. |
5 | ** Contact: https://www.qt.io/licensing/ |
6 | ** |
7 | ** This file is part of the QtCore module of the Qt Toolkit. |
8 | ** |
9 | ** $QT_BEGIN_LICENSE:LGPL$ |
10 | ** Commercial License Usage |
11 | ** Licensees holding valid commercial Qt licenses may use this file in |
12 | ** accordance with the commercial license agreement provided with the |
13 | ** Software or, alternatively, in accordance with the terms contained in |
14 | ** a written agreement between you and The Qt Company. For licensing terms |
15 | ** and conditions see https://www.qt.io/terms-conditions. For further |
16 | ** information use the contact form at https://www.qt.io/contact-us. |
17 | ** |
18 | ** GNU Lesser General Public License Usage |
19 | ** Alternatively, this file may be used under the terms of the GNU Lesser |
20 | ** General Public License version 3 as published by the Free Software |
21 | ** Foundation and appearing in the file LICENSE.LGPL3 included in the |
22 | ** packaging of this file. Please review the following information to |
23 | ** ensure the GNU Lesser General Public License version 3 requirements |
24 | ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. |
25 | ** |
26 | ** GNU General Public License Usage |
27 | ** Alternatively, this file may be used under the terms of the GNU |
28 | ** General Public License version 2.0 or (at your option) the GNU General |
29 | ** Public license version 3 or any later version approved by the KDE Free |
30 | ** Qt Foundation. The licenses are as published by the Free Software |
31 | ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 |
32 | ** included in the packaging of this file. Please review the following |
33 | ** information to ensure the GNU General Public License requirements will |
34 | ** be met: https://www.gnu.org/licenses/gpl-2.0.html and |
35 | ** https://www.gnu.org/licenses/gpl-3.0.html. |
36 | ** |
37 | ** $QT_END_LICENSE$ |
38 | ** |
39 | ****************************************************************************/ |
40 | |
41 | #ifndef QATOMIC_CXX11_H |
42 | #define QATOMIC_CXX11_H |
43 | |
44 | #include <QtCore/qgenericatomic.h> |
45 | #include <atomic> |
46 | |
47 | QT_BEGIN_NAMESPACE |
48 | |
49 | #if 0 |
50 | // silence syncqt warnings |
51 | QT_END_NAMESPACE |
52 | #pragma qt_sync_skip_header_check |
53 | #pragma qt_sync_stop_processing |
54 | #endif |
55 | |
56 | /* Attempt to detect whether the atomic operations exist in hardware |
57 | * or whether they are emulated by way of a lock. |
58 | * |
59 | * C++11 29.4 [atomics.lockfree] p1 says |
60 | * |
61 | * The ATOMIC_..._LOCK_FREE macros indicate the lock-free property of the |
62 | * corresponding atomic types, with the signed and unsigned variants grouped |
63 | * together. The properties also apply to the corresponding (partial) |
64 | * specializations of the atomic template. A value of 0 indicates that the |
65 | * types are never lock-free. A value of 1 indicates that the types are |
66 | * sometimes lock-free. A value of 2 indicates that the types are always |
67 | * lock-free. |
68 | * |
69 | * We have a problem when the value is 1: we'd need to check at runtime, but |
70 | * QAtomicInteger requires a constexpr answer (defect introduced in Qt 5.0). So |
71 | * we'll err in the side of caution and say it isn't. |
72 | */ |
73 | |
74 | // ### Qt 6: make non-constexpr (see above) |
75 | template <int N> struct QAtomicTraits |
76 | { static Q_DECL_CONSTEXPR inline bool isLockFree(); }; |
77 | |
78 | #define Q_ATOMIC_INT32_IS_SUPPORTED |
79 | #if ATOMIC_INT_LOCK_FREE == 2 |
80 | # define Q_ATOMIC_INT_REFERENCE_COUNTING_IS_ALWAYS_NATIVE |
81 | # define Q_ATOMIC_INT_TEST_AND_SET_IS_ALWAYS_NATIVE |
82 | # define Q_ATOMIC_INT_FETCH_AND_STORE_IS_ALWAYS_NATIVE |
83 | # define Q_ATOMIC_INT_FETCH_AND_ADD_IS_ALWAYS_NATIVE |
84 | # define Q_ATOMIC_INT32_REFERENCE_COUNTING_IS_ALWAYS_NATIVE |
85 | # define Q_ATOMIC_INT32_TEST_AND_SET_IS_ALWAYS_NATIVE |
86 | # define Q_ATOMIC_INT32_FETCH_AND_STORE_IS_ALWAYS_NATIVE |
87 | # define Q_ATOMIC_INT32_FETCH_AND_ADD_IS_ALWAYS_NATIVE |
88 | |
89 | template <> Q_DECL_CONSTEXPR inline bool QAtomicTraits<4>::isLockFree() |
90 | { return true; } |
91 | #elif ATOMIC_INT_LOCK_FREE == 1 |
92 | # define Q_ATOMIC_INT_REFERENCE_COUNTING_IS_SOMETIMES_NATIVE |
93 | # define Q_ATOMIC_INT_TEST_AND_SET_IS_SOMETIMES_NATIVE |
94 | # define Q_ATOMIC_INT_FETCH_AND_STORE_IS_SOMETIMES_NATIVE |
95 | # define Q_ATOMIC_INT_FETCH_AND_ADD_IS_SOMETIMES_NATIVE |
96 | # define Q_ATOMIC_INT32_REFERENCE_COUNTING_IS_SOMETIMES_NATIVE |
97 | # define Q_ATOMIC_INT32_TEST_AND_SET_IS_SOMETIMES_NATIVE |
98 | # define Q_ATOMIC_INT32_FETCH_AND_STORE_IS_SOMETIMES_NATIVE |
99 | # define Q_ATOMIC_INT32_FETCH_AND_ADD_IS_SOMETIMES_NATIVE |
100 | |
101 | template <> Q_DECL_CONSTEXPR inline bool QAtomicTraits<4>::isLockFree() |
102 | { return false; } |
103 | #else |
104 | # define Q_ATOMIC_INT_REFERENCE_COUNTING_IS_NEVER_NATIVE |
105 | # define Q_ATOMIC_INT_TEST_AND_SET_IS_NEVER_NATIVE |
106 | # define Q_ATOMIC_INT_FETCH_AND_STORE_IS_NEVER_NATIVE |
107 | # define Q_ATOMIC_INT_FETCH_AND_ADD_IS_NEVER_NATIVE |
108 | # define Q_ATOMIC_INT32_REFERENCE_COUNTING_IS_NEVER_NATIVE |
109 | # define Q_ATOMIC_INT32_TEST_AND_SET_IS_NEVER_NATIVE |
110 | # define Q_ATOMIC_INT32_FETCH_AND_STORE_IS_NEVER_NATIVE |
111 | # define Q_ATOMIC_INT32_FETCH_AND_ADD_IS_NEVER_NATIVE |
112 | |
113 | template <> Q_DECL_CONSTEXPR inline bool QAtomicTraits<4>::isLockFree() |
114 | { return false; } |
115 | #endif |
116 | |
117 | #if ATOMIC_POINTER_LOCK_FREE == 2 |
118 | # define Q_ATOMIC_POINTER_REFERENCE_COUNTING_IS_ALWAYS_NATIVE |
119 | # define Q_ATOMIC_POINTER_TEST_AND_SET_IS_ALWAYS_NATIVE |
120 | # define Q_ATOMIC_POINTER_FETCH_AND_STORE_IS_ALWAYS_NATIVE |
121 | # define Q_ATOMIC_POINTER_FETCH_AND_ADD_IS_ALWAYS_NATIVE |
122 | #elif ATOMIC_POINTER_LOCK_FREE == 1 |
123 | # define Q_ATOMIC_POINTER_REFERENCE_COUNTING_IS_SOMETIMES_NATIVE |
124 | # define Q_ATOMIC_POINTER_TEST_AND_SET_IS_SOMETIMES_NATIVE |
125 | # define Q_ATOMIC_POINTER_FETCH_AND_STORE_IS_SOMETIMES_NATIVE |
126 | # define Q_ATOMIC_POINTER_FETCH_AND_ADD_IS_SOMETIMES_NATIVE |
127 | #else |
128 | # define Q_ATOMIC_POINTER_REFERENCE_COUNTING_IS_NEVER_NATIVE |
129 | # define Q_ATOMIC_POINTER_TEST_AND_SET_IS_NEVER_NATIVE |
130 | # define Q_ATOMIC_POINTER_FETCH_AND_STORE_IS_NEVER_NATIVE |
131 | # define Q_ATOMIC_POINTER_FETCH_AND_ADD_IS_NEVER_NATIVE |
132 | #endif |
133 | |
134 | template<> struct QAtomicOpsSupport<1> { enum { IsSupported = 1 }; }; |
135 | #define Q_ATOMIC_INT8_IS_SUPPORTED |
136 | #if ATOMIC_CHAR_LOCK_FREE == 2 |
137 | # define Q_ATOMIC_INT8_REFERENCE_COUNTING_IS_ALWAYS_NATIVE |
138 | # define Q_ATOMIC_INT8_TEST_AND_SET_IS_ALWAYS_NATIVE |
139 | # define Q_ATOMIC_INT8_FETCH_AND_STORE_IS_ALWAYS_NATIVE |
140 | # define Q_ATOMIC_INT8_FETCH_AND_ADD_IS_ALWAYS_NATIVE |
141 | |
142 | template <> Q_DECL_CONSTEXPR inline bool QAtomicTraits<1>::isLockFree() |
143 | { return true; } |
144 | #elif ATOMIC_CHAR_LOCK_FREE == 1 |
145 | # define Q_ATOMIC_INT8_REFERENCE_COUNTING_IS_SOMETIMES_NATIVE |
146 | # define Q_ATOMIC_INT8_TEST_AND_SET_IS_SOMETIMES_NATIVE |
147 | # define Q_ATOMIC_INT8_FETCH_AND_STORE_IS_SOMETIMES_NATIVE |
148 | # define Q_ATOMIC_INT8_FETCH_AND_ADD_IS_SOMETIMES_NATIVE |
149 | |
150 | template <> Q_DECL_CONSTEXPR inline bool QAtomicTraits<1>::isLockFree() |
151 | { return false; } |
152 | #else |
153 | # define Q_ATOMIC_INT8_REFERENCE_COUNTING_IS_NEVER_NATIVE |
154 | # define Q_ATOMIC_INT8_TEST_AND_SET_IS_NEVER_NATIVE |
155 | # define Q_ATOMIC_INT8_FETCH_AND_STORE_IS_NEVER_NATIVE |
156 | # define Q_ATOMIC_INT8_FETCH_AND_ADD_IS_NEVER_NATIVE |
157 | |
158 | template <> Q_DECL_CONSTEXPR bool QAtomicTraits<1>::isLockFree() |
159 | { return false; } |
160 | #endif |
161 | |
162 | template<> struct QAtomicOpsSupport<2> { enum { IsSupported = 1 }; }; |
163 | #define Q_ATOMIC_INT16_IS_SUPPORTED |
164 | #if ATOMIC_SHORT_LOCK_FREE == 2 |
165 | # define Q_ATOMIC_INT16_REFERENCE_COUNTING_IS_ALWAYS_NATIVE |
166 | # define Q_ATOMIC_INT16_TEST_AND_SET_IS_ALWAYS_NATIVE |
167 | # define Q_ATOMIC_INT16_FETCH_AND_STORE_IS_ALWAYS_NATIVE |
168 | # define Q_ATOMIC_INT16_FETCH_AND_ADD_IS_ALWAYS_NATIVE |
169 | |
170 | template <> Q_DECL_CONSTEXPR inline bool QAtomicTraits<2>::isLockFree() |
171 | { return false; } |
172 | #elif ATOMIC_SHORT_LOCK_FREE == 1 |
173 | # define Q_ATOMIC_INT16_REFERENCE_COUNTING_IS_SOMETIMES_NATIVE |
174 | # define Q_ATOMIC_INT16_TEST_AND_SET_IS_SOMETIMES_NATIVE |
175 | # define Q_ATOMIC_INT16_FETCH_AND_STORE_IS_SOMETIMES_NATIVE |
176 | # define Q_ATOMIC_INT16_FETCH_AND_ADD_IS_SOMETIMES_NATIVE |
177 | |
178 | template <> Q_DECL_CONSTEXPR inline bool QAtomicTraits<2>::isLockFree() |
179 | { return false; } |
180 | #else |
181 | # define Q_ATOMIC_INT16_REFERENCE_COUNTING_IS_NEVER_NATIVE |
182 | # define Q_ATOMIC_INT16_TEST_AND_SET_IS_NEVER_NATIVE |
183 | # define Q_ATOMIC_INT16_FETCH_AND_STORE_IS_NEVER_NATIVE |
184 | # define Q_ATOMIC_INT16_FETCH_AND_ADD_IS_NEVER_NATIVE |
185 | |
186 | template <> Q_DECL_CONSTEXPR inline bool QAtomicTraits<2>::isLockFree() |
187 | { return false; } |
188 | #endif |
189 | |
190 | #if QT_CONFIG(std_atomic64) |
191 | template<> struct QAtomicOpsSupport<8> { enum { IsSupported = 1 }; }; |
192 | # define Q_ATOMIC_INT64_IS_SUPPORTED |
193 | # if ATOMIC_LLONG_LOCK_FREE == 2 |
194 | # define Q_ATOMIC_INT64_REFERENCE_COUNTING_IS_ALWAYS_NATIVE |
195 | # define Q_ATOMIC_INT64_TEST_AND_SET_IS_ALWAYS_NATIVE |
196 | # define Q_ATOMIC_INT64_FETCH_AND_STORE_IS_ALWAYS_NATIVE |
197 | # define Q_ATOMIC_INT64_FETCH_AND_ADD_IS_ALWAYS_NATIVE |
198 | |
199 | template <> Q_DECL_CONSTEXPR inline bool QAtomicTraits<8>::isLockFree() |
200 | { return true; } |
201 | # elif ATOMIC_LLONG_LOCK_FREE == 1 |
202 | # define Q_ATOMIC_INT64_REFERENCE_COUNTING_IS_SOMETIMES_NATIVE |
203 | # define Q_ATOMIC_INT64_TEST_AND_SET_IS_SOMETIMES_NATIVE |
204 | # define Q_ATOMIC_INT64_FETCH_AND_STORE_IS_SOMETIMES_NATIVE |
205 | # define Q_ATOMIC_INT64_FETCH_AND_ADD_IS_SOMETIMES_NATIVE |
206 | |
207 | template <> Q_DECL_CONSTEXPR inline bool QAtomicTraits<8>::isLockFree() |
208 | { return false; } |
209 | # else |
210 | # define Q_ATOMIC_INT64_REFERENCE_COUNTING_IS_NEVER_NATIVE |
211 | # define Q_ATOMIC_INT64_TEST_AND_SET_IS_NEVER_NATIVE |
212 | # define Q_ATOMIC_INT64_FETCH_AND_STORE_IS_NEVER_NATIVE |
213 | # define Q_ATOMIC_INT64_FETCH_AND_ADD_IS_NEVER_NATIVE |
214 | |
215 | template <> Q_DECL_CONSTEXPR inline bool QAtomicTraits<8>::isLockFree() |
216 | { return false; } |
217 | # endif |
218 | #endif |
219 | |
220 | template <typename X> struct QAtomicOps |
221 | { |
222 | typedef std::atomic<X> Type; |
223 | |
224 | template <typename T> static inline |
225 | T load(const std::atomic<T> &_q_value) noexcept |
226 | { |
227 | return _q_value.load(std::memory_order_relaxed); |
228 | } |
229 | |
230 | template <typename T> static inline |
231 | T load(const volatile std::atomic<T> &_q_value) noexcept |
232 | { |
233 | return _q_value.load(std::memory_order_relaxed); |
234 | } |
235 | |
236 | template <typename T> static inline |
237 | T loadRelaxed(const std::atomic<T> &_q_value) noexcept |
238 | { |
239 | return _q_value.load(std::memory_order_relaxed); |
240 | } |
241 | |
242 | template <typename T> static inline |
243 | T loadRelaxed(const volatile std::atomic<T> &_q_value) noexcept |
244 | { |
245 | return _q_value.load(std::memory_order_relaxed); |
246 | } |
247 | |
248 | template <typename T> static inline |
249 | T loadAcquire(const std::atomic<T> &_q_value) noexcept |
250 | { |
251 | return _q_value.load(std::memory_order_acquire); |
252 | } |
253 | |
254 | template <typename T> static inline |
255 | T loadAcquire(const volatile std::atomic<T> &_q_value) noexcept |
256 | { |
257 | return _q_value.load(std::memory_order_acquire); |
258 | } |
259 | |
260 | template <typename T> static inline |
261 | void store(std::atomic<T> &_q_value, T newValue) noexcept |
262 | { |
263 | _q_value.store(newValue, std::memory_order_relaxed); |
264 | } |
265 | |
266 | template <typename T> static inline |
267 | void storeRelaxed(std::atomic<T> &_q_value, T newValue) noexcept |
268 | { |
269 | _q_value.store(newValue, std::memory_order_relaxed); |
270 | } |
271 | |
272 | template <typename T> static inline |
273 | void storeRelease(std::atomic<T> &_q_value, T newValue) noexcept |
274 | { |
275 | _q_value.store(newValue, std::memory_order_release); |
276 | } |
277 | |
278 | static inline Q_DECL_CONSTEXPR bool isReferenceCountingNative() noexcept { return isTestAndSetNative(); } |
279 | static inline Q_DECL_CONSTEXPR bool isReferenceCountingWaitFree() noexcept { return false; } |
280 | template <typename T> |
281 | static inline bool ref(std::atomic<T> &_q_value) |
282 | { |
283 | return ++_q_value != 0; |
284 | } |
285 | |
286 | template <typename T> |
287 | static inline bool deref(std::atomic<T> &_q_value) noexcept |
288 | { |
289 | return --_q_value != 0; |
290 | } |
291 | |
292 | static inline Q_DECL_CONSTEXPR bool isTestAndSetNative() noexcept |
293 | { return QAtomicTraits<sizeof(X)>::isLockFree(); } |
294 | static inline Q_DECL_CONSTEXPR bool isTestAndSetWaitFree() noexcept { return false; } |
295 | |
296 | template <typename T> |
297 | static bool testAndSetRelaxed(std::atomic<T> &_q_value, T expectedValue, T newValue, T *currentValue = nullptr) noexcept |
298 | { |
299 | bool tmp = _q_value.compare_exchange_strong(expectedValue, newValue, std::memory_order_relaxed, std::memory_order_relaxed); |
300 | if (currentValue) |
301 | *currentValue = expectedValue; |
302 | return tmp; |
303 | } |
304 | |
305 | template <typename T> |
306 | static bool testAndSetAcquire(std::atomic<T> &_q_value, T expectedValue, T newValue, T *currentValue = nullptr) noexcept |
307 | { |
308 | bool tmp = _q_value.compare_exchange_strong(expectedValue, newValue, std::memory_order_acquire, std::memory_order_acquire); |
309 | if (currentValue) |
310 | *currentValue = expectedValue; |
311 | return tmp; |
312 | } |
313 | |
314 | template <typename T> |
315 | static bool testAndSetRelease(std::atomic<T> &_q_value, T expectedValue, T newValue, T *currentValue = nullptr) noexcept |
316 | { |
317 | bool tmp = _q_value.compare_exchange_strong(expectedValue, newValue, std::memory_order_release, std::memory_order_relaxed); |
318 | if (currentValue) |
319 | *currentValue = expectedValue; |
320 | return tmp; |
321 | } |
322 | |
323 | template <typename T> |
324 | static bool testAndSetOrdered(std::atomic<T> &_q_value, T expectedValue, T newValue, T *currentValue = nullptr) noexcept |
325 | { |
326 | bool tmp = _q_value.compare_exchange_strong(expectedValue, newValue, std::memory_order_acq_rel, std::memory_order_acquire); |
327 | if (currentValue) |
328 | *currentValue = expectedValue; |
329 | return tmp; |
330 | } |
331 | |
332 | static inline Q_DECL_CONSTEXPR bool isFetchAndStoreNative() noexcept { return isTestAndSetNative(); } |
333 | static inline Q_DECL_CONSTEXPR bool isFetchAndStoreWaitFree() noexcept { return false; } |
334 | |
335 | template <typename T> |
336 | static T fetchAndStoreRelaxed(std::atomic<T> &_q_value, T newValue) noexcept |
337 | { |
338 | return _q_value.exchange(newValue, std::memory_order_relaxed); |
339 | } |
340 | |
341 | template <typename T> |
342 | static T fetchAndStoreAcquire(std::atomic<T> &_q_value, T newValue) noexcept |
343 | { |
344 | return _q_value.exchange(newValue, std::memory_order_acquire); |
345 | } |
346 | |
347 | template <typename T> |
348 | static T fetchAndStoreRelease(std::atomic<T> &_q_value, T newValue) noexcept |
349 | { |
350 | return _q_value.exchange(newValue, std::memory_order_release); |
351 | } |
352 | |
353 | template <typename T> |
354 | static T fetchAndStoreOrdered(std::atomic<T> &_q_value, T newValue) noexcept |
355 | { |
356 | return _q_value.exchange(newValue, std::memory_order_acq_rel); |
357 | } |
358 | |
359 | static inline Q_DECL_CONSTEXPR bool isFetchAndAddNative() noexcept { return isTestAndSetNative(); } |
360 | static inline Q_DECL_CONSTEXPR bool isFetchAndAddWaitFree() noexcept { return false; } |
361 | |
362 | template <typename T> static inline |
363 | T fetchAndAddRelaxed(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) noexcept |
364 | { |
365 | return _q_value.fetch_add(valueToAdd, std::memory_order_relaxed); |
366 | } |
367 | |
368 | template <typename T> static inline |
369 | T fetchAndAddAcquire(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) noexcept |
370 | { |
371 | return _q_value.fetch_add(valueToAdd, std::memory_order_acquire); |
372 | } |
373 | |
374 | template <typename T> static inline |
375 | T fetchAndAddRelease(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) noexcept |
376 | { |
377 | return _q_value.fetch_add(valueToAdd, std::memory_order_release); |
378 | } |
379 | |
380 | template <typename T> static inline |
381 | T fetchAndAddOrdered(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) noexcept |
382 | { |
383 | return _q_value.fetch_add(valueToAdd, std::memory_order_acq_rel); |
384 | } |
385 | |
386 | template <typename T> static inline |
387 | T fetchAndSubRelaxed(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) noexcept |
388 | { |
389 | return _q_value.fetch_sub(valueToAdd, std::memory_order_relaxed); |
390 | } |
391 | |
392 | template <typename T> static inline |
393 | T fetchAndSubAcquire(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) noexcept |
394 | { |
395 | return _q_value.fetch_sub(valueToAdd, std::memory_order_acquire); |
396 | } |
397 | |
398 | template <typename T> static inline |
399 | T fetchAndSubRelease(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) noexcept |
400 | { |
401 | return _q_value.fetch_sub(valueToAdd, std::memory_order_release); |
402 | } |
403 | |
404 | template <typename T> static inline |
405 | T fetchAndSubOrdered(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) noexcept |
406 | { |
407 | return _q_value.fetch_sub(valueToAdd, std::memory_order_acq_rel); |
408 | } |
409 | |
410 | template <typename T> static inline |
411 | T fetchAndAndRelaxed(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) noexcept |
412 | { |
413 | return _q_value.fetch_and(valueToAdd, std::memory_order_relaxed); |
414 | } |
415 | |
416 | template <typename T> static inline |
417 | T fetchAndAndAcquire(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) noexcept |
418 | { |
419 | return _q_value.fetch_and(valueToAdd, std::memory_order_acquire); |
420 | } |
421 | |
422 | template <typename T> static inline |
423 | T fetchAndAndRelease(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) noexcept |
424 | { |
425 | return _q_value.fetch_and(valueToAdd, std::memory_order_release); |
426 | } |
427 | |
428 | template <typename T> static inline |
429 | T fetchAndAndOrdered(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) noexcept |
430 | { |
431 | return _q_value.fetch_and(valueToAdd, std::memory_order_acq_rel); |
432 | } |
433 | |
434 | template <typename T> static inline |
435 | T fetchAndOrRelaxed(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) noexcept |
436 | { |
437 | return _q_value.fetch_or(valueToAdd, std::memory_order_relaxed); |
438 | } |
439 | |
440 | template <typename T> static inline |
441 | T fetchAndOrAcquire(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) noexcept |
442 | { |
443 | return _q_value.fetch_or(valueToAdd, std::memory_order_acquire); |
444 | } |
445 | |
446 | template <typename T> static inline |
447 | T fetchAndOrRelease(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) noexcept |
448 | { |
449 | return _q_value.fetch_or(valueToAdd, std::memory_order_release); |
450 | } |
451 | |
452 | template <typename T> static inline |
453 | T fetchAndOrOrdered(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) noexcept |
454 | { |
455 | return _q_value.fetch_or(valueToAdd, std::memory_order_acq_rel); |
456 | } |
457 | |
458 | template <typename T> static inline |
459 | T fetchAndXorRelaxed(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) noexcept |
460 | { |
461 | return _q_value.fetch_xor(valueToAdd, std::memory_order_relaxed); |
462 | } |
463 | |
464 | template <typename T> static inline |
465 | T fetchAndXorAcquire(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) noexcept |
466 | { |
467 | return _q_value.fetch_xor(valueToAdd, std::memory_order_acquire); |
468 | } |
469 | |
470 | template <typename T> static inline |
471 | T fetchAndXorRelease(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) noexcept |
472 | { |
473 | return _q_value.fetch_xor(valueToAdd, std::memory_order_release); |
474 | } |
475 | |
476 | template <typename T> static inline |
477 | T fetchAndXorOrdered(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) noexcept |
478 | { |
479 | return _q_value.fetch_xor(valueToAdd, std::memory_order_acq_rel); |
480 | } |
481 | }; |
482 | |
483 | #if defined(Q_COMPILER_CONSTEXPR) |
484 | # define Q_BASIC_ATOMIC_INITIALIZER(a) { a } |
485 | #else |
486 | # define Q_BASIC_ATOMIC_INITIALIZER(a) { ATOMIC_VAR_INIT(a) } |
487 | #endif |
488 | |
489 | QT_END_NAMESPACE |
490 | |
491 | #endif // QATOMIC_CXX0X_H |
492 | |