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_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
199template <> 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
207template <> 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
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) 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
489QT_END_NAMESPACE
490
491#endif // QATOMIC_CXX0X_H
492