Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 10:07:16

0001 // Copyright (C) 2011 Thiago Macieira <thiago@kde.org>
0002 // Copyright (C) 2016 Intel Corporation.
0003 // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
0004 
0005 #ifndef QATOMIC_CXX11_H
0006 #define QATOMIC_CXX11_H
0007 
0008 #include <QtCore/qgenericatomic.h>
0009 #include <QtCore/qyieldcpu.h>
0010 #include <atomic>
0011 
0012 QT_BEGIN_NAMESPACE
0013 
0014 #if 0
0015 // silence syncqt warnings
0016 QT_END_NAMESPACE
0017 #pragma qt_sync_skip_header_check
0018 #pragma qt_sync_stop_processing
0019 #endif
0020 
0021 /* Attempt to detect whether the atomic operations exist in hardware
0022  * or whether they are emulated by way of a lock.
0023  *
0024  * C++11 29.4 [atomics.lockfree] p1 says
0025  *
0026  *  The ATOMIC_..._LOCK_FREE macros indicate the lock-free property of the
0027  *  corresponding atomic types, with the signed and unsigned variants grouped
0028  *  together. The properties also apply to the corresponding (partial)
0029  *  specializations of the atomic template. A value of 0 indicates that the
0030  *  types are never lock-free. A value of 1 indicates that the types are
0031  *  sometimes lock-free. A value of 2 indicates that the types are always
0032  *  lock-free.
0033  *
0034  * We have a problem when the value is 1: we'd need to check at runtime, but
0035  * QAtomicInteger requires a constexpr answer (defect introduced in Qt 5.0). So
0036  * we'll err in the side of caution and say it isn't.
0037  */
0038 template <int N> struct QAtomicTraits
0039 { static inline bool isLockFree(); };
0040 
0041 #define Q_ATOMIC_INT32_IS_SUPPORTED
0042 #if ATOMIC_INT_LOCK_FREE == 2
0043 #  define Q_ATOMIC_INT_REFERENCE_COUNTING_IS_ALWAYS_NATIVE
0044 #  define Q_ATOMIC_INT_TEST_AND_SET_IS_ALWAYS_NATIVE
0045 #  define Q_ATOMIC_INT_FETCH_AND_STORE_IS_ALWAYS_NATIVE
0046 #  define Q_ATOMIC_INT_FETCH_AND_ADD_IS_ALWAYS_NATIVE
0047 #  define Q_ATOMIC_INT32_REFERENCE_COUNTING_IS_ALWAYS_NATIVE
0048 #  define Q_ATOMIC_INT32_TEST_AND_SET_IS_ALWAYS_NATIVE
0049 #  define Q_ATOMIC_INT32_FETCH_AND_STORE_IS_ALWAYS_NATIVE
0050 #  define Q_ATOMIC_INT32_FETCH_AND_ADD_IS_ALWAYS_NATIVE
0051 
0052 template <> inline bool QAtomicTraits<4>::isLockFree()
0053 { return true; }
0054 #elif ATOMIC_INT_LOCK_FREE == 1
0055 #  define Q_ATOMIC_INT_REFERENCE_COUNTING_IS_SOMETIMES_NATIVE
0056 #  define Q_ATOMIC_INT_TEST_AND_SET_IS_SOMETIMES_NATIVE
0057 #  define Q_ATOMIC_INT_FETCH_AND_STORE_IS_SOMETIMES_NATIVE
0058 #  define Q_ATOMIC_INT_FETCH_AND_ADD_IS_SOMETIMES_NATIVE
0059 #  define Q_ATOMIC_INT32_REFERENCE_COUNTING_IS_SOMETIMES_NATIVE
0060 #  define Q_ATOMIC_INT32_TEST_AND_SET_IS_SOMETIMES_NATIVE
0061 #  define Q_ATOMIC_INT32_FETCH_AND_STORE_IS_SOMETIMES_NATIVE
0062 #  define Q_ATOMIC_INT32_FETCH_AND_ADD_IS_SOMETIMES_NATIVE
0063 
0064 template <> inline bool QAtomicTraits<4>::isLockFree()
0065 { return false; }
0066 #else
0067 #  define Q_ATOMIC_INT_REFERENCE_COUNTING_IS_NEVER_NATIVE
0068 #  define Q_ATOMIC_INT_TEST_AND_SET_IS_NEVER_NATIVE
0069 #  define Q_ATOMIC_INT_FETCH_AND_STORE_IS_NEVER_NATIVE
0070 #  define Q_ATOMIC_INT_FETCH_AND_ADD_IS_NEVER_NATIVE
0071 #  define Q_ATOMIC_INT32_REFERENCE_COUNTING_IS_NEVER_NATIVE
0072 #  define Q_ATOMIC_INT32_TEST_AND_SET_IS_NEVER_NATIVE
0073 #  define Q_ATOMIC_INT32_FETCH_AND_STORE_IS_NEVER_NATIVE
0074 #  define Q_ATOMIC_INT32_FETCH_AND_ADD_IS_NEVER_NATIVE
0075 
0076 template <> inline bool QAtomicTraits<4>::isLockFree()
0077 { return false; }
0078 #endif
0079 
0080 #if ATOMIC_POINTER_LOCK_FREE == 2
0081 #  define Q_ATOMIC_POINTER_REFERENCE_COUNTING_IS_ALWAYS_NATIVE
0082 #  define Q_ATOMIC_POINTER_TEST_AND_SET_IS_ALWAYS_NATIVE
0083 #  define Q_ATOMIC_POINTER_FETCH_AND_STORE_IS_ALWAYS_NATIVE
0084 #  define Q_ATOMIC_POINTER_FETCH_AND_ADD_IS_ALWAYS_NATIVE
0085 #elif ATOMIC_POINTER_LOCK_FREE == 1
0086 #  define Q_ATOMIC_POINTER_REFERENCE_COUNTING_IS_SOMETIMES_NATIVE
0087 #  define Q_ATOMIC_POINTER_TEST_AND_SET_IS_SOMETIMES_NATIVE
0088 #  define Q_ATOMIC_POINTER_FETCH_AND_STORE_IS_SOMETIMES_NATIVE
0089 #  define Q_ATOMIC_POINTER_FETCH_AND_ADD_IS_SOMETIMES_NATIVE
0090 #else
0091 #  define Q_ATOMIC_POINTER_REFERENCE_COUNTING_IS_NEVER_NATIVE
0092 #  define Q_ATOMIC_POINTER_TEST_AND_SET_IS_NEVER_NATIVE
0093 #  define Q_ATOMIC_POINTER_FETCH_AND_STORE_IS_NEVER_NATIVE
0094 #  define Q_ATOMIC_POINTER_FETCH_AND_ADD_IS_NEVER_NATIVE
0095 #endif
0096 
0097 template<> struct QAtomicOpsSupport<1> { enum { IsSupported = 1 }; };
0098 #define Q_ATOMIC_INT8_IS_SUPPORTED
0099 #if ATOMIC_CHAR_LOCK_FREE == 2
0100 #  define Q_ATOMIC_INT8_REFERENCE_COUNTING_IS_ALWAYS_NATIVE
0101 #  define Q_ATOMIC_INT8_TEST_AND_SET_IS_ALWAYS_NATIVE
0102 #  define Q_ATOMIC_INT8_FETCH_AND_STORE_IS_ALWAYS_NATIVE
0103 #  define Q_ATOMIC_INT8_FETCH_AND_ADD_IS_ALWAYS_NATIVE
0104 
0105 template <> inline bool QAtomicTraits<1>::isLockFree()
0106 { return true; }
0107 #elif ATOMIC_CHAR_LOCK_FREE == 1
0108 #  define Q_ATOMIC_INT8_REFERENCE_COUNTING_IS_SOMETIMES_NATIVE
0109 #  define Q_ATOMIC_INT8_TEST_AND_SET_IS_SOMETIMES_NATIVE
0110 #  define Q_ATOMIC_INT8_FETCH_AND_STORE_IS_SOMETIMES_NATIVE
0111 #  define Q_ATOMIC_INT8_FETCH_AND_ADD_IS_SOMETIMES_NATIVE
0112 
0113 template <> inline bool QAtomicTraits<1>::isLockFree()
0114 { return false; }
0115 #else
0116 #  define Q_ATOMIC_INT8_REFERENCE_COUNTING_IS_NEVER_NATIVE
0117 #  define Q_ATOMIC_INT8_TEST_AND_SET_IS_NEVER_NATIVE
0118 #  define Q_ATOMIC_INT8_FETCH_AND_STORE_IS_NEVER_NATIVE
0119 #  define Q_ATOMIC_INT8_FETCH_AND_ADD_IS_NEVER_NATIVE
0120 
0121 template <> bool QAtomicTraits<1>::isLockFree()
0122 { return false; }
0123 #endif
0124 
0125 template<> struct QAtomicOpsSupport<2> { enum { IsSupported = 1 }; };
0126 #define Q_ATOMIC_INT16_IS_SUPPORTED
0127 #if ATOMIC_SHORT_LOCK_FREE == 2
0128 #  define Q_ATOMIC_INT16_REFERENCE_COUNTING_IS_ALWAYS_NATIVE
0129 #  define Q_ATOMIC_INT16_TEST_AND_SET_IS_ALWAYS_NATIVE
0130 #  define Q_ATOMIC_INT16_FETCH_AND_STORE_IS_ALWAYS_NATIVE
0131 #  define Q_ATOMIC_INT16_FETCH_AND_ADD_IS_ALWAYS_NATIVE
0132 
0133 template <> inline bool QAtomicTraits<2>::isLockFree()
0134 { return false; }
0135 #elif ATOMIC_SHORT_LOCK_FREE == 1
0136 #  define Q_ATOMIC_INT16_REFERENCE_COUNTING_IS_SOMETIMES_NATIVE
0137 #  define Q_ATOMIC_INT16_TEST_AND_SET_IS_SOMETIMES_NATIVE
0138 #  define Q_ATOMIC_INT16_FETCH_AND_STORE_IS_SOMETIMES_NATIVE
0139 #  define Q_ATOMIC_INT16_FETCH_AND_ADD_IS_SOMETIMES_NATIVE
0140 
0141 template <> inline bool QAtomicTraits<2>::isLockFree()
0142 { return false; }
0143 #else
0144 #  define Q_ATOMIC_INT16_REFERENCE_COUNTING_IS_NEVER_NATIVE
0145 #  define Q_ATOMIC_INT16_TEST_AND_SET_IS_NEVER_NATIVE
0146 #  define Q_ATOMIC_INT16_FETCH_AND_STORE_IS_NEVER_NATIVE
0147 #  define Q_ATOMIC_INT16_FETCH_AND_ADD_IS_NEVER_NATIVE
0148 
0149 template <> inline bool QAtomicTraits<2>::isLockFree()
0150 { return false; }
0151 #endif
0152 
0153 #if !defined(QT_BOOTSTRAPPED) && QT_CONFIG(std_atomic64)
0154 template<> struct QAtomicOpsSupport<8> { enum { IsSupported = 1 }; };
0155 #  define Q_ATOMIC_INT64_IS_SUPPORTED
0156 #  if ATOMIC_LLONG_LOCK_FREE == 2
0157 #    define Q_ATOMIC_INT64_REFERENCE_COUNTING_IS_ALWAYS_NATIVE
0158 #    define Q_ATOMIC_INT64_TEST_AND_SET_IS_ALWAYS_NATIVE
0159 #    define Q_ATOMIC_INT64_FETCH_AND_STORE_IS_ALWAYS_NATIVE
0160 #    define Q_ATOMIC_INT64_FETCH_AND_ADD_IS_ALWAYS_NATIVE
0161 
0162 template <> inline bool QAtomicTraits<8>::isLockFree()
0163 { return true; }
0164 #  elif ATOMIC_LLONG_LOCK_FREE == 1
0165 #    define Q_ATOMIC_INT64_REFERENCE_COUNTING_IS_SOMETIMES_NATIVE
0166 #    define Q_ATOMIC_INT64_TEST_AND_SET_IS_SOMETIMES_NATIVE
0167 #    define Q_ATOMIC_INT64_FETCH_AND_STORE_IS_SOMETIMES_NATIVE
0168 #    define Q_ATOMIC_INT64_FETCH_AND_ADD_IS_SOMETIMES_NATIVE
0169 
0170 template <> inline bool QAtomicTraits<8>::isLockFree()
0171 { return false; }
0172 #  else
0173 #    define Q_ATOMIC_INT64_REFERENCE_COUNTING_IS_NEVER_NATIVE
0174 #    define Q_ATOMIC_INT64_TEST_AND_SET_IS_NEVER_NATIVE
0175 #    define Q_ATOMIC_INT64_FETCH_AND_STORE_IS_NEVER_NATIVE
0176 #    define Q_ATOMIC_INT64_FETCH_AND_ADD_IS_NEVER_NATIVE
0177 
0178 template <> inline bool QAtomicTraits<8>::isLockFree()
0179 { return false; }
0180 #  endif
0181 #endif
0182 
0183 template <typename X> struct QAtomicOps
0184 {
0185     typedef std::atomic<X> Type;
0186 
0187     template <typename T> static inline
0188     T load(const std::atomic<T> &_q_value) noexcept
0189     {
0190         return _q_value.load(std::memory_order_relaxed);
0191     }
0192 
0193     template <typename T> static inline
0194     T load(const volatile std::atomic<T> &_q_value) noexcept
0195     {
0196         return _q_value.load(std::memory_order_relaxed);
0197     }
0198 
0199     template <typename T> static inline
0200     T loadRelaxed(const std::atomic<T> &_q_value) noexcept
0201     {
0202         return _q_value.load(std::memory_order_relaxed);
0203     }
0204 
0205     template <typename T> static inline
0206     T loadRelaxed(const volatile std::atomic<T> &_q_value) noexcept
0207     {
0208         return _q_value.load(std::memory_order_relaxed);
0209     }
0210 
0211     template <typename T> static inline
0212     T loadAcquire(const std::atomic<T> &_q_value) noexcept
0213     {
0214         return _q_value.load(std::memory_order_acquire);
0215     }
0216 
0217     template <typename T> static inline
0218     T loadAcquire(const volatile std::atomic<T> &_q_value) noexcept
0219     {
0220         return _q_value.load(std::memory_order_acquire);
0221     }
0222 
0223     template <typename T> static inline
0224     void store(std::atomic<T> &_q_value, T newValue) noexcept
0225     {
0226         _q_value.store(newValue, std::memory_order_relaxed);
0227     }
0228 
0229     template <typename T> static inline
0230     void storeRelaxed(std::atomic<T> &_q_value, T newValue) noexcept
0231     {
0232         _q_value.store(newValue, std::memory_order_relaxed);
0233     }
0234 
0235     template <typename T> static inline
0236     void storeRelease(std::atomic<T> &_q_value, T newValue) noexcept
0237     {
0238         _q_value.store(newValue, std::memory_order_release);
0239     }
0240 
0241     static inline bool isReferenceCountingNative() noexcept { return isTestAndSetNative(); }
0242     static inline constexpr bool isReferenceCountingWaitFree() noexcept { return false; }
0243     template <typename T>
0244     static inline bool ref(std::atomic<T> &_q_value)
0245     {
0246         /* Conceptually, we want to
0247          *    return ++_q_value != 0;
0248          * However, that would be sequentially consistent, and thus stronger
0249          * than what we need. Based on
0250          * http://eel.is/c++draft/atomics.types.memop#6, we know that
0251          * pre-increment is equivalent to fetch_add(1) + 1. Unlike
0252          * pre-increment, fetch_add takes a memory order argument, so we can get
0253          * the desired acquire-release semantics.
0254          * One last gotcha is that fetch_add(1) + 1 would need to be converted
0255          * back to T, because it's susceptible to integer promotion. To sidestep
0256          * this issue and to avoid UB on signed overflow, we rewrite the
0257          * expression to:
0258          */
0259         return _q_value.fetch_add(1, std::memory_order_acq_rel) != T(-1);
0260     }
0261 
0262     template <typename T>
0263     static inline bool deref(std::atomic<T> &_q_value) noexcept
0264     {
0265         // compare with ref
0266         return _q_value.fetch_sub(1, std::memory_order_acq_rel) != T(1);
0267     }
0268 
0269     static inline bool isTestAndSetNative() noexcept
0270     { return QAtomicTraits<sizeof(X)>::isLockFree(); }
0271     static inline constexpr bool isTestAndSetWaitFree() noexcept { return false; }
0272 
0273     template <typename T>
0274     static bool testAndSetRelaxed(std::atomic<T> &_q_value, T expectedValue, T newValue, T *currentValue = nullptr) noexcept
0275     {
0276         bool tmp = _q_value.compare_exchange_strong(expectedValue, newValue, std::memory_order_relaxed, std::memory_order_relaxed);
0277         if (currentValue)
0278             *currentValue = expectedValue;
0279         return tmp;
0280     }
0281 
0282     template <typename T>
0283     static bool testAndSetAcquire(std::atomic<T> &_q_value, T expectedValue, T newValue, T *currentValue = nullptr) noexcept
0284     {
0285         bool tmp = _q_value.compare_exchange_strong(expectedValue, newValue, std::memory_order_acquire, std::memory_order_acquire);
0286         if (currentValue)
0287             *currentValue = expectedValue;
0288         return tmp;
0289     }
0290 
0291     template <typename T>
0292     static bool testAndSetRelease(std::atomic<T> &_q_value, T expectedValue, T newValue, T *currentValue = nullptr) noexcept
0293     {
0294         bool tmp = _q_value.compare_exchange_strong(expectedValue, newValue, std::memory_order_release, std::memory_order_relaxed);
0295         if (currentValue)
0296             *currentValue = expectedValue;
0297         return tmp;
0298     }
0299 
0300     template <typename T>
0301     static bool testAndSetOrdered(std::atomic<T> &_q_value, T expectedValue, T newValue, T *currentValue = nullptr) noexcept
0302     {
0303         bool tmp = _q_value.compare_exchange_strong(expectedValue, newValue, std::memory_order_acq_rel, std::memory_order_acquire);
0304         if (currentValue)
0305             *currentValue = expectedValue;
0306         return tmp;
0307     }
0308 
0309     static inline bool isFetchAndStoreNative() noexcept { return isTestAndSetNative(); }
0310     static inline constexpr bool isFetchAndStoreWaitFree() noexcept { return false; }
0311 
0312     template <typename T>
0313     static T fetchAndStoreRelaxed(std::atomic<T> &_q_value, T newValue) noexcept
0314     {
0315         return _q_value.exchange(newValue, std::memory_order_relaxed);
0316     }
0317 
0318     template <typename T>
0319     static T fetchAndStoreAcquire(std::atomic<T> &_q_value, T newValue) noexcept
0320     {
0321         return _q_value.exchange(newValue, std::memory_order_acquire);
0322     }
0323 
0324     template <typename T>
0325     static T fetchAndStoreRelease(std::atomic<T> &_q_value, T newValue) noexcept
0326     {
0327         return _q_value.exchange(newValue, std::memory_order_release);
0328     }
0329 
0330     template <typename T>
0331     static T fetchAndStoreOrdered(std::atomic<T> &_q_value, T newValue) noexcept
0332     {
0333         return _q_value.exchange(newValue, std::memory_order_acq_rel);
0334     }
0335 
0336     static inline bool isFetchAndAddNative() noexcept { return isTestAndSetNative(); }
0337     static inline constexpr bool isFetchAndAddWaitFree() noexcept { return false; }
0338 
0339     template <typename T> static inline
0340     T fetchAndAddRelaxed(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) noexcept
0341     {
0342         return _q_value.fetch_add(valueToAdd, std::memory_order_relaxed);
0343     }
0344 
0345     template <typename T> static inline
0346     T fetchAndAddAcquire(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) noexcept
0347     {
0348         return _q_value.fetch_add(valueToAdd, std::memory_order_acquire);
0349     }
0350 
0351     template <typename T> static inline
0352     T fetchAndAddRelease(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) noexcept
0353     {
0354         return _q_value.fetch_add(valueToAdd, std::memory_order_release);
0355     }
0356 
0357     template <typename T> static inline
0358     T fetchAndAddOrdered(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) noexcept
0359     {
0360         return _q_value.fetch_add(valueToAdd, std::memory_order_acq_rel);
0361     }
0362 
0363     template <typename T> static inline
0364     T fetchAndSubRelaxed(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) noexcept
0365     {
0366         return _q_value.fetch_sub(valueToAdd, std::memory_order_relaxed);
0367     }
0368 
0369     template <typename T> static inline
0370     T fetchAndSubAcquire(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) noexcept
0371     {
0372         return _q_value.fetch_sub(valueToAdd, std::memory_order_acquire);
0373     }
0374 
0375     template <typename T> static inline
0376     T fetchAndSubRelease(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) noexcept
0377     {
0378         return _q_value.fetch_sub(valueToAdd, std::memory_order_release);
0379     }
0380 
0381     template <typename T> static inline
0382     T fetchAndSubOrdered(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) noexcept
0383     {
0384         return _q_value.fetch_sub(valueToAdd, std::memory_order_acq_rel);
0385     }
0386 
0387     template <typename T> static inline
0388     T fetchAndAndRelaxed(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) noexcept
0389     {
0390         return _q_value.fetch_and(valueToAdd, std::memory_order_relaxed);
0391     }
0392 
0393     template <typename T> static inline
0394     T fetchAndAndAcquire(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) noexcept
0395     {
0396         return _q_value.fetch_and(valueToAdd, std::memory_order_acquire);
0397     }
0398 
0399     template <typename T> static inline
0400     T fetchAndAndRelease(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) noexcept
0401     {
0402         return _q_value.fetch_and(valueToAdd, std::memory_order_release);
0403     }
0404 
0405     template <typename T> static inline
0406     T fetchAndAndOrdered(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) noexcept
0407     {
0408         return _q_value.fetch_and(valueToAdd, std::memory_order_acq_rel);
0409     }
0410 
0411     template <typename T> static inline
0412     T fetchAndOrRelaxed(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) noexcept
0413     {
0414         return _q_value.fetch_or(valueToAdd, std::memory_order_relaxed);
0415     }
0416 
0417     template <typename T> static inline
0418     T fetchAndOrAcquire(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) noexcept
0419     {
0420         return _q_value.fetch_or(valueToAdd, std::memory_order_acquire);
0421     }
0422 
0423     template <typename T> static inline
0424     T fetchAndOrRelease(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) noexcept
0425     {
0426         return _q_value.fetch_or(valueToAdd, std::memory_order_release);
0427     }
0428 
0429     template <typename T> static inline
0430     T fetchAndOrOrdered(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) noexcept
0431     {
0432         return _q_value.fetch_or(valueToAdd, std::memory_order_acq_rel);
0433     }
0434 
0435     template <typename T> static inline
0436     T fetchAndXorRelaxed(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) noexcept
0437     {
0438         return _q_value.fetch_xor(valueToAdd, std::memory_order_relaxed);
0439     }
0440 
0441     template <typename T> static inline
0442     T fetchAndXorAcquire(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) noexcept
0443     {
0444         return _q_value.fetch_xor(valueToAdd, std::memory_order_acquire);
0445     }
0446 
0447     template <typename T> static inline
0448     T fetchAndXorRelease(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) noexcept
0449     {
0450         return _q_value.fetch_xor(valueToAdd, std::memory_order_release);
0451     }
0452 
0453     template <typename T> static inline
0454     T fetchAndXorOrdered(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) noexcept
0455     {
0456         return _q_value.fetch_xor(valueToAdd, std::memory_order_acq_rel);
0457     }
0458 };
0459 
0460 #  define Q_BASIC_ATOMIC_INITIALIZER(a)     { a }
0461 
0462 QT_END_NAMESPACE
0463 
0464 #endif // QATOMIC_CXX0X_H