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