summaryrefslogtreecommitdiffstats
path: root/src/corelib/thread/qgenericatomic.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/corelib/thread/qgenericatomic.h')
-rw-r--r--src/corelib/thread/qgenericatomic.h160
1 files changed, 159 insertions, 1 deletions
diff --git a/src/corelib/thread/qgenericatomic.h b/src/corelib/thread/qgenericatomic.h
index 3a213f6a25..0c66d45855 100644
--- a/src/corelib/thread/qgenericatomic.h
+++ b/src/corelib/thread/qgenericatomic.h
@@ -43,6 +43,7 @@
#define QGENERICATOMIC_H
#include <QtCore/qglobal.h>
+#include <QtCore/qtypeinfo.h>
QT_BEGIN_NAMESPACE
@@ -60,7 +61,8 @@ QT_END_NAMESPACE
#define always_inline
#endif
-template<typename T> struct QAtomicIntegerTraits { enum { IsInteger = 0 }; };
+template<int> struct QAtomicOpsSupport { enum { IsSupported = 0 }; };
+template<> struct QAtomicOpsSupport<4> { enum { IsSupported = 1 }; };
template <typename T> struct QAtomicAdditiveType
{
@@ -140,6 +142,8 @@ template <typename BaseClass> struct QGenericAtomicOps
static inline Q_DECL_CONSTEXPR bool isTestAndSetWaitFree() Q_DECL_NOTHROW;
template <typename T, typename X> static inline
bool testAndSetRelaxed(T &_q_value, X expectedValue, X newValue) Q_DECL_NOTHROW;
+ template <typename T, typename X> static inline
+ bool testAndSetRelaxed(T &_q_value, X expectedValue, X newValue, X *currentValue) Q_DECL_NOTHROW;
#endif
template <typename T, typename X> static inline always_inline
@@ -164,6 +168,28 @@ template <typename BaseClass> struct QGenericAtomicOps
return BaseClass::testAndSetRelaxed(_q_value, expectedValue, newValue);
}
+ template <typename T, typename X> static inline always_inline
+ bool testAndSetAcquire(T &_q_value, X expectedValue, X newValue, X *currentValue) Q_DECL_NOTHROW
+ {
+ bool tmp = BaseClass::testAndSetRelaxed(_q_value, expectedValue, newValue, currentValue);
+ BaseClass::acquireMemoryFence(_q_value);
+ return tmp;
+ }
+
+ template <typename T, typename X> static inline always_inline
+ bool testAndSetRelease(T &_q_value, X expectedValue, X newValue, X *currentValue) Q_DECL_NOTHROW
+ {
+ BaseClass::releaseMemoryFence(_q_value);
+ return BaseClass::testAndSetRelaxed(_q_value, expectedValue, newValue, currentValue);
+ }
+
+ template <typename T, typename X> static inline always_inline
+ bool testAndSetOrdered(T &_q_value, X expectedValue, X newValue, X *currentValue) Q_DECL_NOTHROW
+ {
+ BaseClass::orderedMemoryFence(_q_value);
+ return BaseClass::testAndSetRelaxed(_q_value, expectedValue, newValue, currentValue);
+ }
+
static inline Q_DECL_CONSTEXPR bool isFetchAndStoreNative() Q_DECL_NOTHROW { return false; }
static inline Q_DECL_CONSTEXPR bool isFetchAndStoreWaitFree() Q_DECL_NOTHROW { return false; }
@@ -234,6 +260,138 @@ template <typename BaseClass> struct QGenericAtomicOps
BaseClass::orderedMemoryFence(_q_value);
return BaseClass::fetchAndAddRelaxed(_q_value, valueToAdd);
}
+
+ template <typename T> static inline always_inline
+ T fetchAndSubRelaxed(T &_q_value, typename QAtomicAdditiveType<T>::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 <typename T> static inline always_inline
+ T fetchAndSubAcquire(T &_q_value, typename QAtomicAdditiveType<T>::AdditiveT operand) Q_DECL_NOTHROW
+ {
+ T tmp = BaseClass::fetchAndSubRelaxed(_q_value, operand);
+ BaseClass::acquireMemoryFence(_q_value);
+ return tmp;
+ }
+
+ template <typename T> static inline always_inline
+ T fetchAndSubRelease(T &_q_value, typename QAtomicAdditiveType<T>::AdditiveT operand) Q_DECL_NOTHROW
+ {
+ BaseClass::releaseMemoryFence(_q_value);
+ return BaseClass::fetchAndSubRelaxed(_q_value, operand);
+ }
+
+ template <typename T> static inline always_inline
+ T fetchAndSubOrdered(T &_q_value, typename QAtomicAdditiveType<T>::AdditiveT operand) Q_DECL_NOTHROW
+ {
+ BaseClass::orderedMemoryFence(_q_value);
+ return BaseClass::fetchAndSubRelaxed(_q_value, operand);
+ }
+
+ template <typename T> static inline always_inline
+ T fetchAndAndRelaxed(T &_q_value, typename QtPrivate::QEnableIf<QTypeInfo<T>::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 <typename T> static inline always_inline
+ T fetchAndAndAcquire(T &_q_value, typename QtPrivate::QEnableIf<QTypeInfo<T>::isIntegral, T>::Type operand) Q_DECL_NOTHROW
+ {
+ T tmp = BaseClass::fetchAndAndRelaxed(_q_value, operand);
+ BaseClass::acquireMemoryFence(_q_value);
+ return tmp;
+ }
+
+ template <typename T> static inline always_inline
+ T fetchAndAndRelease(T &_q_value, typename QtPrivate::QEnableIf<QTypeInfo<T>::isIntegral, T>::Type operand) Q_DECL_NOTHROW
+ {
+ BaseClass::releaseMemoryFence(_q_value);
+ return BaseClass::fetchAndAndRelaxed(_q_value, operand);
+ }
+
+ template <typename T> static inline always_inline
+ T fetchAndAndOrdered(T &_q_value, typename QtPrivate::QEnableIf<QTypeInfo<T>::isIntegral, T>::Type operand) Q_DECL_NOTHROW
+ {
+ BaseClass::orderedMemoryFence(_q_value);
+ return BaseClass::fetchAndAndRelaxed(_q_value, operand);
+ }
+
+ template <typename T> static inline always_inline
+ T fetchAndOrRelaxed(T &_q_value, typename QtPrivate::QEnableIf<QTypeInfo<T>::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 <typename T> static inline always_inline
+ T fetchAndOrAcquire(T &_q_value, typename QtPrivate::QEnableIf<QTypeInfo<T>::isIntegral, T>::Type operand) Q_DECL_NOTHROW
+ {
+ T tmp = BaseClass::fetchAndOrRelaxed(_q_value, operand);
+ BaseClass::acquireMemoryFence(_q_value);
+ return tmp;
+ }
+
+ template <typename T> static inline always_inline
+ T fetchAndOrRelease(T &_q_value, typename QtPrivate::QEnableIf<QTypeInfo<T>::isIntegral, T>::Type operand) Q_DECL_NOTHROW
+ {
+ BaseClass::releaseMemoryFence(_q_value);
+ return BaseClass::fetchAndOrRelaxed(_q_value, operand);
+ }
+
+ template <typename T> static inline always_inline
+ T fetchAndOrOrdered(T &_q_value, typename QtPrivate::QEnableIf<QTypeInfo<T>::isIntegral, T>::Type operand) Q_DECL_NOTHROW
+ {
+ BaseClass::orderedMemoryFence(_q_value);
+ return BaseClass::fetchAndOrRelaxed(_q_value, operand);
+ }
+
+ template <typename T> static inline always_inline
+ T fetchAndXorRelaxed(T &_q_value, typename QtPrivate::QEnableIf<QTypeInfo<T>::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 <typename T> static inline always_inline
+ T fetchAndXorAcquire(T &_q_value, typename QtPrivate::QEnableIf<QTypeInfo<T>::isIntegral, T>::Type operand) Q_DECL_NOTHROW
+ {
+ T tmp = BaseClass::fetchAndXorRelaxed(_q_value, operand);
+ BaseClass::acquireMemoryFence(_q_value);
+ return tmp;
+ }
+
+ template <typename T> static inline always_inline
+ T fetchAndXorRelease(T &_q_value, typename QtPrivate::QEnableIf<QTypeInfo<T>::isIntegral, T>::Type operand) Q_DECL_NOTHROW
+ {
+ BaseClass::releaseMemoryFence(_q_value);
+ return BaseClass::fetchAndXorRelaxed(_q_value, operand);
+ }
+
+ template <typename T> static inline always_inline
+ T fetchAndXorOrdered(T &_q_value, typename QtPrivate::QEnableIf<QTypeInfo<T>::isIntegral, T>::Type operand) Q_DECL_NOTHROW
+ {
+ BaseClass::orderedMemoryFence(_q_value);
+ return BaseClass::fetchAndXorRelaxed(_q_value, operand);
+ }
};
#undef always_inline