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
isLockFree()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
isLockFree()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
isLockFree()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