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
47QT_BEGIN_NAMESPACE
48
49#if 0
50// silence syncqt warnings
51QT_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)
75template <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
89template <> 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
101template <> 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
113template <> 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
134template<> 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
142template <> 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
150template <> 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
158template <> Q_DECL_CONSTEXPR bool QAtomicTraits<1>::isLockFree()
159{ return false; }
160#endif
161
162template<> 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
170template <> 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
178template <> 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
186template <> Q_DECL_CONSTEXPR inline bool QAtomicTraits<2>::isLockFree()
187{ return false; }
188#endif
189
190#if QT_CONFIG(std_atomic64)
191template<> struct QAtomicOpsSupport<8> { enum { IsSupported = 1 }; };
192# define Q_ATOMIC_INT64_IS_SUPPORTED
193# if ATOMIC_LLONG_LOCK_FREE == 2
194# define Q_ATOMIC_INT16_REFERENCE_COUNTING_IS_ALWAYS_NATIVE
195# define Q_ATOMIC_INT16_TEST_AND_SET_IS_ALWAYS_NATIVE
196# define Q_ATOMIC_INT16_FETCH_AND_STORE_IS_ALWAYS_NATIVE
197# define Q_ATOMIC_INT16_FETCH_AND_ADD_IS_ALWAYS_NATIVE
198
199template <> Q_DECL_CONSTEXPR inline bool QAtomicTraits<8>::isLockFree()
200{ return true; }
201# elif ATOMIC_LLONG_LOCK_FREE == 1
202# define Q_ATOMIC_INT16_REFERENCE_COUNTING_IS_SOMETIMES_NATIVE
203# define Q_ATOMIC_INT16_TEST_AND_SET_IS_SOMETIMES_NATIVE
204# define Q_ATOMIC_INT16_FETCH_AND_STORE_IS_SOMETIMES_NATIVE
205# define Q_ATOMIC_INT16_FETCH_AND_ADD_IS_SOMETIMES_NATIVE
206
207template <> Q_DECL_CONSTEXPR inline bool QAtomicTraits<8>::isLockFree()
208{ return false; }
209# else
210# define Q_ATOMIC_INT16_REFERENCE_COUNTING_IS_NEVER_NATIVE
211# define Q_ATOMIC_INT16_TEST_AND_SET_IS_NEVER_NATIVE
212# define Q_ATOMIC_INT16_FETCH_AND_STORE_IS_NEVER_NATIVE
213# define Q_ATOMIC_INT16_FETCH_AND_ADD_IS_NEVER_NATIVE
214
215template <> Q_DECL_CONSTEXPR inline bool QAtomicTraits<8>::isLockFree()
216{ return false; }
217# endif
218#endif
219
220template <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) Q_DECL_NOTHROW
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) Q_DECL_NOTHROW
232 {
233 return _q_value.load(std::memory_order_relaxed);
234 }
235
236 template <typename T> static inline
237 T loadAcquire(const std::atomic<T> &_q_value) Q_DECL_NOTHROW
238 {
239 return _q_value.load(std::memory_order_acquire);
240 }
241
242 template <typename T> static inline
243 T loadAcquire(const volatile std::atomic<T> &_q_value) Q_DECL_NOTHROW
244 {
245 return _q_value.load(std::memory_order_acquire);
246 }
247
248 template <typename T> static inline
249 void store(std::atomic<T> &_q_value, T newValue) Q_DECL_NOTHROW
250 {
251 _q_value.store(newValue, std::memory_order_relaxed);
252 }
253
254 template <typename T> static inline
255 void storeRelease(std::atomic<T> &_q_value, T newValue) Q_DECL_NOTHROW
256 {
257 _q_value.store(newValue, std::memory_order_release);
258 }
259
260 static inline Q_DECL_CONSTEXPR bool isReferenceCountingNative() Q_DECL_NOTHROW { return isTestAndSetNative(); }
261 static inline Q_DECL_CONSTEXPR bool isReferenceCountingWaitFree() Q_DECL_NOTHROW { return false; }
262 template <typename T>
263 static inline bool ref(std::atomic<T> &_q_value)
264 {
265 return ++_q_value != 0;
266 }
267
268 template <typename T>
269 static inline bool deref(std::atomic<T> &_q_value) Q_DECL_NOTHROW
270 {
271 return --_q_value != 0;
272 }
273
274 static inline Q_DECL_CONSTEXPR bool isTestAndSetNative() Q_DECL_NOTHROW
275 { return QAtomicTraits<sizeof(X)>::isLockFree(); }
276 static inline Q_DECL_CONSTEXPR bool isTestAndSetWaitFree() Q_DECL_NOTHROW { return false; }
277
278 template <typename T>
279 static bool testAndSetRelaxed(std::atomic<T> &_q_value, T expectedValue, T newValue, T *currentValue = nullptr) Q_DECL_NOTHROW
280 {
281 bool tmp = _q_value.compare_exchange_strong(expectedValue, newValue, std::memory_order_relaxed, std::memory_order_relaxed);
282 if (currentValue)
283 *currentValue = expectedValue;
284 return tmp;
285 }
286
287 template <typename T>
288 static bool testAndSetAcquire(std::atomic<T> &_q_value, T expectedValue, T newValue, T *currentValue = nullptr) Q_DECL_NOTHROW
289 {
290 bool tmp = _q_value.compare_exchange_strong(expectedValue, newValue, std::memory_order_acquire, std::memory_order_acquire);
291 if (currentValue)
292 *currentValue = expectedValue;
293 return tmp;
294 }
295
296 template <typename T>
297 static bool testAndSetRelease(std::atomic<T> &_q_value, T expectedValue, T newValue, T *currentValue = nullptr) Q_DECL_NOTHROW
298 {
299 bool tmp = _q_value.compare_exchange_strong(expectedValue, newValue, std::memory_order_release, std::memory_order_relaxed);
300 if (currentValue)
301 *currentValue = expectedValue;
302 return tmp;
303 }
304
305 template <typename T>
306 static bool testAndSetOrdered(std::atomic<T> &_q_value, T expectedValue, T newValue, T *currentValue = nullptr) Q_DECL_NOTHROW
307 {
308 bool tmp = _q_value.compare_exchange_strong(expectedValue, newValue, std::memory_order_acq_rel, std::memory_order_acquire);
309 if (currentValue)
310 *currentValue = expectedValue;
311 return tmp;
312 }
313
314 static inline Q_DECL_CONSTEXPR bool isFetchAndStoreNative() Q_DECL_NOTHROW { return isTestAndSetNative(); }
315 static inline Q_DECL_CONSTEXPR bool isFetchAndStoreWaitFree() Q_DECL_NOTHROW { return false; }
316
317 template <typename T>
318 static T fetchAndStoreRelaxed(std::atomic<T> &_q_value, T newValue) Q_DECL_NOTHROW
319 {
320 return _q_value.exchange(newValue, std::memory_order_relaxed);
321 }
322
323 template <typename T>
324 static T fetchAndStoreAcquire(std::atomic<T> &_q_value, T newValue) Q_DECL_NOTHROW
325 {
326 return _q_value.exchange(newValue, std::memory_order_acquire);
327 }
328
329 template <typename T>
330 static T fetchAndStoreRelease(std::atomic<T> &_q_value, T newValue) Q_DECL_NOTHROW
331 {
332 return _q_value.exchange(newValue, std::memory_order_release);
333 }
334
335 template <typename T>
336 static T fetchAndStoreOrdered(std::atomic<T> &_q_value, T newValue) Q_DECL_NOTHROW
337 {
338 return _q_value.exchange(newValue, std::memory_order_acq_rel);
339 }
340
341 static inline Q_DECL_CONSTEXPR bool isFetchAndAddNative() Q_DECL_NOTHROW { return isTestAndSetNative(); }
342 static inline Q_DECL_CONSTEXPR bool isFetchAndAddWaitFree() Q_DECL_NOTHROW { return false; }
343
344 template <typename T> static inline
345 T fetchAndAddRelaxed(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) Q_DECL_NOTHROW
346 {
347 return _q_value.fetch_add(valueToAdd, std::memory_order_relaxed);
348 }
349
350 template <typename T> static inline
351 T fetchAndAddAcquire(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) Q_DECL_NOTHROW
352 {
353 return _q_value.fetch_add(valueToAdd, std::memory_order_acquire);
354 }
355
356 template <typename T> static inline
357 T fetchAndAddRelease(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) Q_DECL_NOTHROW
358 {
359 return _q_value.fetch_add(valueToAdd, std::memory_order_release);
360 }
361
362 template <typename T> static inline
363 T fetchAndAddOrdered(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) Q_DECL_NOTHROW
364 {
365 return _q_value.fetch_add(valueToAdd, std::memory_order_acq_rel);
366 }
367
368 template <typename T> static inline
369 T fetchAndSubRelaxed(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) Q_DECL_NOTHROW
370 {
371 return _q_value.fetch_sub(valueToAdd, std::memory_order_relaxed);
372 }
373
374 template <typename T> static inline
375 T fetchAndSubAcquire(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) Q_DECL_NOTHROW
376 {
377 return _q_value.fetch_sub(valueToAdd, std::memory_order_acquire);
378 }
379
380 template <typename T> static inline
381 T fetchAndSubRelease(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) Q_DECL_NOTHROW
382 {
383 return _q_value.fetch_sub(valueToAdd, std::memory_order_release);
384 }
385
386 template <typename T> static inline
387 T fetchAndSubOrdered(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) Q_DECL_NOTHROW
388 {
389 return _q_value.fetch_sub(valueToAdd, std::memory_order_acq_rel);
390 }
391
392 template <typename T> static inline
393 T fetchAndAndRelaxed(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) Q_DECL_NOTHROW
394 {
395 return _q_value.fetch_and(valueToAdd, std::memory_order_relaxed);
396 }
397
398 template <typename T> static inline
399 T fetchAndAndAcquire(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) Q_DECL_NOTHROW
400 {
401 return _q_value.fetch_and(valueToAdd, std::memory_order_acquire);
402 }
403
404 template <typename T> static inline
405 T fetchAndAndRelease(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) Q_DECL_NOTHROW
406 {
407 return _q_value.fetch_and(valueToAdd, std::memory_order_release);
408 }
409
410 template <typename T> static inline
411 T fetchAndAndOrdered(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) Q_DECL_NOTHROW
412 {
413 return _q_value.fetch_and(valueToAdd, std::memory_order_acq_rel);
414 }
415
416 template <typename T> static inline
417 T fetchAndOrRelaxed(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) Q_DECL_NOTHROW
418 {
419 return _q_value.fetch_or(valueToAdd, std::memory_order_relaxed);
420 }
421
422 template <typename T> static inline
423 T fetchAndOrAcquire(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) Q_DECL_NOTHROW
424 {
425 return _q_value.fetch_or(valueToAdd, std::memory_order_acquire);
426 }
427
428 template <typename T> static inline
429 T fetchAndOrRelease(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) Q_DECL_NOTHROW
430 {
431 return _q_value.fetch_or(valueToAdd, std::memory_order_release);
432 }
433
434 template <typename T> static inline
435 T fetchAndOrOrdered(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) Q_DECL_NOTHROW
436 {
437 return _q_value.fetch_or(valueToAdd, std::memory_order_acq_rel);
438 }
439
440 template <typename T> static inline
441 T fetchAndXorRelaxed(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) Q_DECL_NOTHROW
442 {
443 return _q_value.fetch_xor(valueToAdd, std::memory_order_relaxed);
444 }
445
446 template <typename T> static inline
447 T fetchAndXorAcquire(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) Q_DECL_NOTHROW
448 {
449 return _q_value.fetch_xor(valueToAdd, std::memory_order_acquire);
450 }
451
452 template <typename T> static inline
453 T fetchAndXorRelease(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) Q_DECL_NOTHROW
454 {
455 return _q_value.fetch_xor(valueToAdd, std::memory_order_release);
456 }
457
458 template <typename T> static inline
459 T fetchAndXorOrdered(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) Q_DECL_NOTHROW
460 {
461 return _q_value.fetch_xor(valueToAdd, std::memory_order_acq_rel);
462 }
463};
464
465#if defined(Q_COMPILER_CONSTEXPR) && defined(Q_COMPILER_DEFAULT_MEMBERS) && defined(Q_COMPILER_DELETE_MEMBERS)
466# define Q_BASIC_ATOMIC_INITIALIZER(a) { a }
467#else
468# define Q_BASIC_ATOMIC_INITIALIZER(a) { ATOMIC_VAR_INIT(a) }
469#endif
470
471QT_END_NAMESPACE
472
473#endif // QATOMIC_CXX0X_H
474