From 19c70982517e76d89bb3da931e1390a6386603da Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Wed, 27 Feb 2013 17:25:45 -0800 Subject: Add the rest of the non-volatile members of std::atomic to QBasicAtomic [ChangeLog][QtCore][Atomic support]Added more operations to the atomic classes, including operator T(), operator=(T), operator++, operator--. For the QAtomicInteger, bit-manipulation operations are also provided, both in operator and in fetchAndXxxYyyyyy modes. Change-Id: I39c07be74e15e0a48f9e931f4342b182004dee1a Reviewed-by: David Faure --- src/corelib/thread/qatomic.cpp | 409 +++++++++++++++++++++++++++++++++++- src/corelib/thread/qatomic.h | 33 +++ src/corelib/thread/qbasicatomic.h | 84 +++++++- src/corelib/thread/qgenericatomic.h | 133 ++++++++++++ 4 files changed, 656 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/corelib/thread/qatomic.cpp b/src/corelib/thread/qatomic.cpp index bebdab3080..33e85c1505 100644 --- a/src/corelib/thread/qatomic.cpp +++ b/src/corelib/thread/qatomic.cpp @@ -294,6 +294,29 @@ \sa store(), load() */ +/*! + \fn QAtomicInteger::operator int() const + \since 5.3 + + Atomically loads the value of this QAtomicInteger using a sequentially + consistent memory ordering if possible; or "Acquire" ordering if not. The + value is not modified in any way, but note that there's no guarantee that + it remains so. + + \sa load(), loadAcquire() +*/ + +/*! + \fn QAtomicInteger &QAtomicInteger::operator=(int newValue) + \since 5.3 + + Atomically stores the \a newValue value into this atomic type using a + sequentially consistent memory ordering if possible; or "Release" ordering + if not. This function returns a reference to this object. + + \sa store(), storeRelease() +*/ + /*! \fn bool QAtomicInteger::isReferenceCountingNative() Returns \c true if reference counting is implemented using atomic @@ -315,7 +338,33 @@ access before and after the atomic operation (in program order) may not be re-ordered. - \sa deref() + \sa deref(), operator++() +*/ + +/*! + \fn int QAtomicInteger::operator++() + \since 5.3 + + Atomically pre-increments the value of this QAtomicInteger. Returns the new + value of this atomic. + + This function uses a sequentially consistent memory ordering if possible; + or "Ordered" ordering if not. + + \sa ref(), operator++(int), operator--() +*/ + +/*! + \fn int QAtomicInteger::operator++(int) + \since 5.3 + + Atomically post-increments the value of this QAtomicInteger. Returns the old + value of this atomic. + + This function uses a sequentially consistent memory ordering if possible; + or "Ordered" ordering if not. + + \sa ref(), operator++(), operator--(int) */ /*! \fn bool QAtomicInteger::deref() @@ -327,7 +376,33 @@ access before and after the atomic operation (in program order) may not be re-ordered. - \sa ref() + \sa ref(), operator--() +*/ + +/*! + \fn int QAtomicInteger::operator--() + \since 5.3 + + Atomically pre-decrements the value of this QAtomicInteger. Returns the new + value of this atomic. + + This function uses a sequentially consistent memory ordering if possible; + or "Ordered" ordering if not. + + \sa deref(), operator--(int), operator++() +*/ + +/*! + \fn int QAtomicInteger::operator--(int) + \since 5.3 + + Atomically post-decrements the value of this QAtomicInteger. Returns the old + value of this atomic. + + This function uses a sequentially consistent memory ordering if possible; + or "Ordered" ordering if not. + + \sa deref(), operator--(), operator++(int) */ /*! \fn bool QAtomicInteger::isTestAndSetNative() @@ -485,6 +560,8 @@ This function uses \e relaxed \l {QAtomicInteger#Memory ordering}{memory ordering} semantics, leaving the compiler and processor to freely reorder memory accesses. + + \sa operator+=(), fetchAndSubRelaxed() */ /*! \fn int QAtomicInteger::fetchAndAddAcquire(int valueToAdd) @@ -498,6 +575,8 @@ ordering}{memory ordering} semantics, which ensures that memory access following the atomic operation (in program order) may not be re-ordered before the atomic operation. + + \sa operator+=(), fetchAndSubAcquire() */ /*! \fn int QAtomicInteger::fetchAndAddRelease(int valueToAdd) @@ -511,6 +590,8 @@ ordering}{memory ordering} semantics, which ensures that memory access before the atomic operation (in program order) may not be re-ordered after the atomic operation. + + \sa operator+=(), fetchAndSubRelease() */ /*! \fn int QAtomicInteger::fetchAndAddOrdered(int valueToAdd) @@ -524,6 +605,330 @@ ordering}{memory ordering} semantics, which ensures that memory access before and after the atomic operation (in program order) may not be re-ordered. + + \sa operator+=(), fetchAndSubOrdered() +*/ + +/*! \fn int QAtomicInteger::operator+=(int valueToAdd) + \since 5.3 + + Atomic add-and-fetch. + + Reads the current value of this QAtomicInteger and then adds + \a valueToAdd to the current value, returning the new value value. + + This function uses a sequentially consistent memory ordering if possible; + or "Ordered" ordering if not. + + \sa fetchAndAddOrdered(), operator-=() +*/ + +/*! \fn int QAtomicInteger::fetchAndSubRelaxed(int valueToSub) + \since 5.3 + + Atomic fetch-and-sub. + + Reads the current value of this QAtomicInteger and then subtracts + \a valueToSub to the current value, returning the original value. + + This function uses \e relaxed \l {QAtomicInteger#Memory + ordering}{memory ordering} semantics, leaving the compiler and + processor to freely reorder memory accesses. + + \sa operator-=(), fetchAndAddRelaxed() +*/ + +/*! \fn int QAtomicInteger::fetchAndSubAcquire(int valueToSub) + \since 5.3 + + Atomic fetch-and-sub. + + Reads the current value of this QAtomicInteger and then subtracts + \a valueToSub to the current value, returning the original value. + + This function uses \e acquire \l {QAtomicInteger#Memory + ordering}{memory ordering} semantics, which ensures that memory + access following the atomic operation (in program order) may not + be re-ordered before the atomic operation. + + \sa operator-=(), fetchAndAddAcquire() +*/ + +/*! \fn int QAtomicInteger::fetchAndSubRelease(int valueToSub) + \since 5.3 + + Atomic fetch-and-sub. + + Reads the current value of this QAtomicInteger and then subtracts + \a valueToSub to the current value, returning the original value. + + This function uses \e release \l {QAtomicInteger#Memory + ordering}{memory ordering} semantics, which ensures that memory + access before the atomic operation (in program order) may not be + re-ordered after the atomic operation. + + \sa operator-=(), fetchAndAddRelease() +*/ + +/*! \fn int QAtomicInteger::fetchAndSubOrdered(int valueToSub) + \since 5.3 + + Atomic fetch-and-sub. + + Reads the current value of this QAtomicInteger and then subtracts + \a valueToSub to the current value, returning the original value. + + This function uses \e ordered \l {QAtomicInteger#Memory + ordering}{memory ordering} semantics, which ensures that memory + access before and after the atomic operation (in program order) + may not be re-ordered. + + \sa operator-=(), fetchAndAddOrdered() +*/ + +/*! \fn int QAtomicInteger::operator-=(int valueToSub) + \since 5.3 + + Atomic sub-and-fetch. + + Reads the current value of this QAtomicInteger and then subtracts + \a valueToSub to the current value, returning the new value value. + + This function uses a sequentially consistent memory ordering if possible; + or "Ordered" ordering if not. + + \sa fetchAndSubOrdered(), operator+=() +*/ + +/*! \fn int QAtomicInteger::fetchAndOrRelaxed(int valueToOr) + \since 5.3 + + Atomic fetch-and-or. + + Reads the current value of this QAtomicInteger and then bitwise-ORs + \a valueToOr to the current value, returning the original value. + + This function uses \e relaxed \l {QAtomicInteger#Memory + ordering}{memory ordering} semantics, leaving the compiler and + processor to freely reorder memory accesses. + + \sa operator|=() +*/ + +/*! \fn int QAtomicInteger::fetchAndOrAcquire(int valueToOr) + \since 5.3 + + Atomic fetch-and-or. + + Reads the current value of this QAtomicInteger and then bitwise-ORs + \a valueToOr to the current value, returning the original value. + + This function uses \e acquire \l {QAtomicInteger#Memory + ordering}{memory ordering} semantics, which ensures that memory + access following the atomic operation (in program order) may not + be re-ordered before the atomic operation. + + \sa operator|=() +*/ + +/*! \fn int QAtomicInteger::fetchAndOrRelease(int valueToOr) + \since 5.3 + + Atomic fetch-and-or. + + Reads the current value of this QAtomicInteger and then bitwise-ORs + \a valueToOr to the current value, returning the original value. + + This function uses \e release \l {QAtomicInteger#Memory + ordering}{memory ordering} semantics, which ensures that memory + access before the atomic operation (in program order) may not be + re-ordered after the atomic operation. + + \sa operator|=() +*/ + +/*! \fn int QAtomicInteger::fetchAndOrOrdered(int valueToOr) + \since 5.3 + + Atomic fetch-and-or. + + Reads the current value of this QAtomicInteger and then bitwise-ORs + \a valueToOr to the current value, returning the original value. + + This function uses \e ordered \l {QAtomicInteger#Memory + ordering}{memory ordering} semantics, which ensures that memory + access before and after the atomic operation (in program order) + may not be re-ordered. + + \sa operator|=() +*/ + +/*! \fn int QAtomicInteger::operator|=(int valueToOr) + \since 5.3 + + Atomic or-and-fetch. + + Reads the current value of this QAtomicInteger and then bitwise-ORs + \a valueToOr to the current value, returning the new value value. + + This function uses a sequentially consistent memory ordering if possible; + or "Ordered" ordering if not. + + \sa fetchAndOrOrdered() +*/ + +/*! \fn int QAtomicInteger::fetchAndXorRelaxed(int valueToXor) + \since 5.3 + + Atomic fetch-and-xor. + + Reads the current value of this QAtomicInteger and then bitwise-XORs + \a valueToXor to the current value, returning the original value. + + This function uses \e relaxed \l {QAtomicInteger#Memory + ordering}{memory ordering} semantics, leaving the compiler and + processor to freely reorder memory accesses. + + \sa operator^=() +*/ + +/*! \fn int QAtomicInteger::fetchAndXorAcquire(int valueToXor) + \since 5.3 + + Atomic fetch-and-xor. + + Reads the current value of this QAtomicInteger and then bitwise-XORs + \a valueToXor to the current value, returning the original value. + + This function uses \e acquire \l {QAtomicInteger#Memory + ordering}{memory ordering} semantics, which ensures that memory + access following the atomic operation (in program order) may not + be re-ordered before the atomic operation. + + \sa operator^=() +*/ + +/*! \fn int QAtomicInteger::fetchAndXorRelease(int valueToXor) + \since 5.3 + + Atomic fetch-and-xor. + + Reads the current value of this QAtomicInteger and then bitwise-XORs + \a valueToXor to the current value, returning the original value. + + This function uses \e release \l {QAtomicInteger#Memory + ordering}{memory ordering} semantics, which ensures that memory + access before the atomic operation (in program order) may not be + re-ordered after the atomic operation. + + \sa operator^=() +*/ + +/*! \fn int QAtomicInteger::fetchAndXorOrdered(int valueToXor) + \since 5.3 + + Atomic fetch-and-xor. + + Reads the current value of this QAtomicInteger and then bitwise-XORs + \a valueToXor to the current value, returning the original value. + + This function uses \e ordered \l {QAtomicInteger#Memory + ordering}{memory ordering} semantics, which ensures that memory + access before and after the atomic operation (in program order) + may not be re-ordered. + + \sa operator^=() +*/ + +/*! \fn int QAtomicInteger::operator^=(int valueToXor) + \since 5.3 + + Atomic xor-and-fetch. + + Reads the current value of this QAtomicInteger and then bitwise-XORs + \a valueToXor to the current value, returning the new value value. + + This function uses a sequentially consistent memory ordering if possible; + or "Ordered" ordering if not. + + \sa fetchAndXorOrdered() +*/ + +/*! \fn int QAtomicInteger::fetchAndAndRelaxed(int valueToAnd) + \since 5.3 + + Atomic fetch-and-and. + + Reads the current value of this QAtomicInteger and then bitwise-ANDs + \a valueToAnd to the current value, returning the original value. + + This function uses \e relaxed \l {QAtomicInteger#Memory + ordering}{memory ordering} semantics, leaving the compiler and + processor to freely reorder memory accesses. + + \sa operator&=() +*/ + +/*! \fn int QAtomicInteger::fetchAndAndAcquire(int valueToAnd) + \since 5.3 + + Atomic fetch-and-and. + + Reads the current value of this QAtomicInteger and then bitwise-ANDs + \a valueToAnd to the current value, returning the original value. + + This function uses \e acquire \l {QAtomicInteger#Memory + ordering}{memory ordering} semantics, which ensures that memory + access following the atomic operation (in program order) may not + be re-ordered before the atomic operation. + + \sa operator&=() +*/ + +/*! \fn int QAtomicInteger::fetchAndAndRelease(int valueToAnd) + \since 5.3 + + Atomic fetch-and-and. + + Reads the current value of this QAtomicInteger and then bitwise-ANDs + \a valueToAnd to the current value, returning the original value. + + This function uses \e release \l {QAtomicInteger#Memory + ordering}{memory ordering} semantics, which ensures that memory + access before the atomic operation (in program order) may not be + re-ordered after the atomic operation. + + \sa operator&=() +*/ + +/*! \fn int QAtomicInteger::fetchAndAndOrdered(int valueToAnd) + \since 5.3 + + Atomic fetch-and-and. + + Reads the current value of this QAtomicInteger and then bitwise-ANDs + \a valueToAnd to the current value, returning the original value. + + This function uses \e ordered \l {QAtomicInteger#Memory + ordering}{memory ordering} semantics, which ensures that memory + access before and after the atomic operation (in program order) + may not be re-ordered. + + \sa operator&=() +*/ + +/*! \fn int QAtomicInteger::operator&=(int valueToAnd) + \since 5.3 + + Atomic add-and-fetch. + + Reads the current value of this QAtomicInteger and then bitwise-ANDs + \a valueToAnd to the current value, returning the new value value. + + This function uses a sequentially consistent memory ordering if possible; + or "Ordered" ordering if not. + + \sa fetchAndAndOrdered() */ /*! diff --git a/src/corelib/thread/qatomic.h b/src/corelib/thread/qatomic.h index d79e168cb3..1faaa22d0f 100644 --- a/src/corelib/thread/qatomic.h +++ b/src/corelib/thread/qatomic.h @@ -89,6 +89,9 @@ public: void store(int newValue); void storeRelease(int newValue); + operator int() const; + QAtomicInteger &operator=(int); + static Q_DECL_CONSTEXPR bool isReferenceCountingNative(); static Q_DECL_CONSTEXPR bool isReferenceCountingWaitFree(); @@ -118,6 +121,36 @@ public: int fetchAndAddAcquire(int valueToAdd); int fetchAndAddRelease(int valueToAdd); int fetchAndAddOrdered(int valueToAdd); + + int fetchAndSubRelaxed(int valueToSub); + int fetchAndSubAcquire(int valueToSub); + int fetchAndSubRelease(int valueToSub); + int fetchAndSubOrdered(int valueToSub); + + int fetchAndOrRelaxed(int valueToOr); + int fetchAndOrAcquire(int valueToOr); + int fetchAndOrRelease(int valueToOr); + int fetchAndOrOrdered(int valueToOr); + + int fetchAndAndRelaxed(int valueToAnd); + int fetchAndAndAcquire(int valueToAnd); + int fetchAndAndRelease(int valueToAnd); + int fetchAndAndOrdered(int valueToAnd); + + int fetchAndXorRelaxed(int valueToXor); + int fetchAndXorAcquire(int valueToXor); + int fetchAndXorRelease(int valueToXor); + int fetchAndXorOrdered(int valueToXor); + + int operator++(); + int operator++(int); + int operator--(); + int operator--(int); + int operator+=(int value); + int operator-=(int value); + int operator|=(int value); + int operator&=(int value); + int operator^=(int value); #endif }; diff --git a/src/corelib/thread/qbasicatomic.h b/src/corelib/thread/qbasicatomic.h index b2234bdb80..cf69d34589 100644 --- a/src/corelib/thread/qbasicatomic.h +++ b/src/corelib/thread/qbasicatomic.h @@ -126,6 +126,8 @@ public: T loadAcquire() const Q_DECL_NOTHROW { return Ops::loadAcquire(_q_value); } void storeRelease(T newValue) Q_DECL_NOTHROW { Ops::storeRelease(_q_value, newValue); } + operator T() const Q_DECL_NOTHROW { return loadAcquire(); } + T operator=(T newValue) Q_DECL_NOTHROW { storeRelease(newValue); return newValue; } static Q_DECL_CONSTEXPR bool isReferenceCountingNative() Q_DECL_NOTHROW { return Ops::isReferenceCountingNative(); } static Q_DECL_CONSTEXPR bool isReferenceCountingWaitFree() Q_DECL_NOTHROW { return Ops::isReferenceCountingWaitFree(); } @@ -178,6 +180,63 @@ public: T fetchAndAddOrdered(T valueToAdd) Q_DECL_NOTHROW { return Ops::fetchAndAddOrdered(_q_value, valueToAdd); } + T fetchAndSubRelaxed(T valueToAdd) Q_DECL_NOTHROW + { return Ops::fetchAndSubRelaxed(_q_value, valueToAdd); } + T fetchAndSubAcquire(T valueToAdd) Q_DECL_NOTHROW + { return Ops::fetchAndSubAcquire(_q_value, valueToAdd); } + T fetchAndSubRelease(T valueToAdd) Q_DECL_NOTHROW + { return Ops::fetchAndSubRelease(_q_value, valueToAdd); } + T fetchAndSubOrdered(T valueToAdd) Q_DECL_NOTHROW + { return Ops::fetchAndSubOrdered(_q_value, valueToAdd); } + + T fetchAndAndRelaxed(T valueToAdd) Q_DECL_NOTHROW + { return Ops::fetchAndAndRelaxed(_q_value, valueToAdd); } + T fetchAndAndAcquire(T valueToAdd) Q_DECL_NOTHROW + { return Ops::fetchAndAndAcquire(_q_value, valueToAdd); } + T fetchAndAndRelease(T valueToAdd) Q_DECL_NOTHROW + { return Ops::fetchAndAndRelease(_q_value, valueToAdd); } + T fetchAndAndOrdered(T valueToAdd) Q_DECL_NOTHROW + { return Ops::fetchAndAndOrdered(_q_value, valueToAdd); } + + T fetchAndOrRelaxed(T valueToAdd) Q_DECL_NOTHROW + { return Ops::fetchAndOrRelaxed(_q_value, valueToAdd); } + T fetchAndOrAcquire(T valueToAdd) Q_DECL_NOTHROW + { return Ops::fetchAndOrAcquire(_q_value, valueToAdd); } + T fetchAndOrRelease(T valueToAdd) Q_DECL_NOTHROW + { return Ops::fetchAndOrRelease(_q_value, valueToAdd); } + T fetchAndOrOrdered(T valueToAdd) Q_DECL_NOTHROW + { return Ops::fetchAndOrOrdered(_q_value, valueToAdd); } + + T fetchAndXorRelaxed(T valueToAdd) Q_DECL_NOTHROW + { return Ops::fetchAndXorRelaxed(_q_value, valueToAdd); } + T fetchAndXorAcquire(T valueToAdd) Q_DECL_NOTHROW + { return Ops::fetchAndXorAcquire(_q_value, valueToAdd); } + T fetchAndXorRelease(T valueToAdd) Q_DECL_NOTHROW + { return Ops::fetchAndXorRelease(_q_value, valueToAdd); } + T fetchAndXorOrdered(T valueToAdd) Q_DECL_NOTHROW + { return Ops::fetchAndXorOrdered(_q_value, valueToAdd); } + + T operator++() Q_DECL_NOTHROW + { return fetchAndAddOrdered(1) + 1; } + T operator++(int) Q_DECL_NOTHROW + { return fetchAndAddOrdered(1); } + T operator--() Q_DECL_NOTHROW + { return fetchAndSubOrdered(1) - 1; } + T operator--(int) Q_DECL_NOTHROW + { return fetchAndSubOrdered(1); } + + T operator+=(T v) Q_DECL_NOTHROW + { return fetchAndAddOrdered(v) + v; } + T operator-=(T v) Q_DECL_NOTHROW + { return fetchAndSubOrdered(v) - v; } + T operator&=(T v) Q_DECL_NOTHROW + { return fetchAndAndOrdered(v) & v; } + T operator|=(T v) Q_DECL_NOTHROW + { return fetchAndOrOrdered(v) | v; } + T operator^=(T v) Q_DECL_NOTHROW + { return fetchAndXorOrdered(v) ^ v; } + + #ifdef QT_BASIC_ATOMIC_HAS_CONSTRUCTORS QBasicAtomicInteger() = default; constexpr QBasicAtomicInteger(T value) Q_DECL_NOTHROW : _q_value(value) {} @@ -198,9 +257,10 @@ public: AtomicType _q_value; - // Non-atomic API Type load() const Q_DECL_NOTHROW { return _q_value; } void store(Type newValue) Q_DECL_NOTHROW { _q_value = newValue; } + operator Type() const Q_DECL_NOTHROW { return loadAcquire(); } + Type operator=(Type newValue) Q_DECL_NOTHROW { storeRelease(newValue); return newValue; } // Atomic API, implemented in qatomic_XXX.h Type loadAcquire() const Q_DECL_NOTHROW { return Ops::loadAcquire(_q_value); } @@ -251,6 +311,28 @@ public: Type fetchAndAddOrdered(qptrdiff valueToAdd) Q_DECL_NOTHROW { return Ops::fetchAndAddOrdered(_q_value, valueToAdd); } + Type fetchAndSubRelaxed(qptrdiff valueToAdd) Q_DECL_NOTHROW + { return Ops::fetchAndSubRelaxed(_q_value, valueToAdd); } + Type fetchAndSubAcquire(qptrdiff valueToAdd) Q_DECL_NOTHROW + { return Ops::fetchAndSubAcquire(_q_value, valueToAdd); } + Type fetchAndSubRelease(qptrdiff valueToAdd) Q_DECL_NOTHROW + { return Ops::fetchAndSubRelease(_q_value, valueToAdd); } + Type fetchAndSubOrdered(qptrdiff valueToAdd) Q_DECL_NOTHROW + { return Ops::fetchAndSubOrdered(_q_value, valueToAdd); } + + Type operator++() Q_DECL_NOTHROW + { return fetchAndAddOrdered(1) + 1; } + Type operator++(int) Q_DECL_NOTHROW + { return fetchAndAddOrdered(1); } + Type operator--() Q_DECL_NOTHROW + { return fetchAndSubOrdered(1) - 1; } + Type operator--(int) Q_DECL_NOTHROW + { return fetchAndSubOrdered(1); } + Type operator+=(qptrdiff valueToAdd) Q_DECL_NOTHROW + { return fetchAndAddOrdered(valueToAdd) + valueToAdd; } + Type operator-=(qptrdiff valueToSub) Q_DECL_NOTHROW + { return fetchAndSubOrdered(valueToSub) - valueToSub; } + #ifdef QT_BASIC_ATOMIC_HAS_CONSTRUCTORS QBasicAtomicPointer() = default; constexpr QBasicAtomicPointer(Type value) Q_DECL_NOTHROW : _q_value(value) {} diff --git a/src/corelib/thread/qgenericatomic.h b/src/corelib/thread/qgenericatomic.h index aab0cfbb45..0c66d45855 100644 --- a/src/corelib/thread/qgenericatomic.h +++ b/src/corelib/thread/qgenericatomic.h @@ -43,6 +43,7 @@ #define QGENERICATOMIC_H #include +#include QT_BEGIN_NAMESPACE @@ -259,6 +260,138 @@ template struct QGenericAtomicOps BaseClass::orderedMemoryFence(_q_value); return BaseClass::fetchAndAddRelaxed(_q_value, valueToAdd); } + + template static inline always_inline + T fetchAndSubRelaxed(T &_q_value, typename QAtomicAdditiveType::AdditiveT operand) Q_DECL_NOTHROW + { + // implement fetchAndSub on top of testAndSet + Q_FOREVER { + T tmp = BaseClass::load(_q_value); + if (BaseClass::testAndSetRelaxed(_q_value, tmp, T(tmp - operand))) + return tmp; + } + } + + template static inline always_inline + T fetchAndSubAcquire(T &_q_value, typename QAtomicAdditiveType::AdditiveT operand) Q_DECL_NOTHROW + { + T tmp = BaseClass::fetchAndSubRelaxed(_q_value, operand); + BaseClass::acquireMemoryFence(_q_value); + return tmp; + } + + template static inline always_inline + T fetchAndSubRelease(T &_q_value, typename QAtomicAdditiveType::AdditiveT operand) Q_DECL_NOTHROW + { + BaseClass::releaseMemoryFence(_q_value); + return BaseClass::fetchAndSubRelaxed(_q_value, operand); + } + + template static inline always_inline + T fetchAndSubOrdered(T &_q_value, typename QAtomicAdditiveType::AdditiveT operand) Q_DECL_NOTHROW + { + BaseClass::orderedMemoryFence(_q_value); + return BaseClass::fetchAndSubRelaxed(_q_value, operand); + } + + template static inline always_inline + T fetchAndAndRelaxed(T &_q_value, typename QtPrivate::QEnableIf::isIntegral, T>::Type operand) Q_DECL_NOTHROW + { + // implement fetchAndAnd on top of testAndSet + Q_FOREVER { + T tmp = BaseClass::load(_q_value); + if (BaseClass::testAndSetRelaxed(_q_value, tmp, T(tmp & operand))) + return tmp; + } + } + + template static inline always_inline + T fetchAndAndAcquire(T &_q_value, typename QtPrivate::QEnableIf::isIntegral, T>::Type operand) Q_DECL_NOTHROW + { + T tmp = BaseClass::fetchAndAndRelaxed(_q_value, operand); + BaseClass::acquireMemoryFence(_q_value); + return tmp; + } + + template static inline always_inline + T fetchAndAndRelease(T &_q_value, typename QtPrivate::QEnableIf::isIntegral, T>::Type operand) Q_DECL_NOTHROW + { + BaseClass::releaseMemoryFence(_q_value); + return BaseClass::fetchAndAndRelaxed(_q_value, operand); + } + + template static inline always_inline + T fetchAndAndOrdered(T &_q_value, typename QtPrivate::QEnableIf::isIntegral, T>::Type operand) Q_DECL_NOTHROW + { + BaseClass::orderedMemoryFence(_q_value); + return BaseClass::fetchAndAndRelaxed(_q_value, operand); + } + + template static inline always_inline + T fetchAndOrRelaxed(T &_q_value, typename QtPrivate::QEnableIf::isIntegral, T>::Type operand) Q_DECL_NOTHROW + { + // implement fetchAndOr on top of testAndSet + Q_FOREVER { + T tmp = BaseClass::load(_q_value); + if (BaseClass::testAndSetRelaxed(_q_value, tmp, T(tmp | operand))) + return tmp; + } + } + + template static inline always_inline + T fetchAndOrAcquire(T &_q_value, typename QtPrivate::QEnableIf::isIntegral, T>::Type operand) Q_DECL_NOTHROW + { + T tmp = BaseClass::fetchAndOrRelaxed(_q_value, operand); + BaseClass::acquireMemoryFence(_q_value); + return tmp; + } + + template static inline always_inline + T fetchAndOrRelease(T &_q_value, typename QtPrivate::QEnableIf::isIntegral, T>::Type operand) Q_DECL_NOTHROW + { + BaseClass::releaseMemoryFence(_q_value); + return BaseClass::fetchAndOrRelaxed(_q_value, operand); + } + + template static inline always_inline + T fetchAndOrOrdered(T &_q_value, typename QtPrivate::QEnableIf::isIntegral, T>::Type operand) Q_DECL_NOTHROW + { + BaseClass::orderedMemoryFence(_q_value); + return BaseClass::fetchAndOrRelaxed(_q_value, operand); + } + + template static inline always_inline + T fetchAndXorRelaxed(T &_q_value, typename QtPrivate::QEnableIf::isIntegral, T>::Type operand) Q_DECL_NOTHROW + { + // implement fetchAndXor on top of testAndSet + Q_FOREVER { + T tmp = BaseClass::load(_q_value); + if (BaseClass::testAndSetRelaxed(_q_value, tmp, T(tmp ^ operand))) + return tmp; + } + } + + template static inline always_inline + T fetchAndXorAcquire(T &_q_value, typename QtPrivate::QEnableIf::isIntegral, T>::Type operand) Q_DECL_NOTHROW + { + T tmp = BaseClass::fetchAndXorRelaxed(_q_value, operand); + BaseClass::acquireMemoryFence(_q_value); + return tmp; + } + + template static inline always_inline + T fetchAndXorRelease(T &_q_value, typename QtPrivate::QEnableIf::isIntegral, T>::Type operand) Q_DECL_NOTHROW + { + BaseClass::releaseMemoryFence(_q_value); + return BaseClass::fetchAndXorRelaxed(_q_value, operand); + } + + template static inline always_inline + T fetchAndXorOrdered(T &_q_value, typename QtPrivate::QEnableIf::isIntegral, T>::Type operand) Q_DECL_NOTHROW + { + BaseClass::orderedMemoryFence(_q_value); + return BaseClass::fetchAndXorRelaxed(_q_value, operand); + } }; #undef always_inline -- cgit v1.2.3