From 307c03497301015c418d4bfe462b14ed9cdf2f1b Mon Sep 17 00:00:00 2001 From: "Bradley T. Hughes" Date: Mon, 30 Jan 2012 15:04:06 +0100 Subject: [PATCH] Port the Windows atomic implementation to use QGenericAtomicOps MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit First, we do not need to have the QT_INTERLOCKED_REMOVE_VOLATILE(a) macro anymore either, since the value stored in QBasicAtomicInteger is not volatile. Windows provides Interlocked*Pointer() functions in some configurations, so we provide a partial specialization of QAtomicOps for pointer types. For integer types, QAtomicOps selects an implementation based on the size of the type. At the moment, we only support 32-bit types, but it will be possible to add 64-bit later. Note that the 32-bit specialization of QAtomicOpsBySize declares the Type typedef as long, not int, since the Windows Interlocked*() API takes parameters as longs and long pointers. Since this typedef differs from the type given to QBasicAtomicInteger by the QBasicAtomicInt typedef, we need to templatise the _q_value parameter separately from the other arguments in QGenericAtomicOps. This templatisation would be necessary to port other architectures, such as PA_RISC, where we need to have an int[4] array in the atomic type while the arguments do not need this array. Change-Id: Id71fa1ae334da2023553cb402b45e6c285f1d344 Reviewed-by: Friedemann Kleint Reviewed-by: João Abecasis Reviewed-by: Thiago Macieira --- src/corelib/arch/qatomic_windows.h | 335 ++++++++++------------------ src/corelib/thread/qbasicatomic.h | 5 +- src/corelib/thread/qgenericatomic.h | 40 ++-- 3 files changed, 134 insertions(+), 246 deletions(-) diff --git a/src/corelib/arch/qatomic_windows.h b/src/corelib/arch/qatomic_windows.h index 5a8547fb05..caac54b0e4 100644 --- a/src/corelib/arch/qatomic_windows.h +++ b/src/corelib/arch/qatomic_windows.h @@ -42,17 +42,16 @@ #ifndef QATOMIC_WINDOWS_H #define QATOMIC_WINDOWS_H -#ifndef Q_CC_MSVC +#ifdef Q_CC_MSVC -// Mingw and other GCC platforms get inline assembly +#include -# ifdef __i386__ -# include "QtCore/qatomic_i386.h" -# else -# include "QtCore/qatomic_x86_64.h" -# endif +QT_BEGIN_HEADER +QT_BEGIN_NAMESPACE -#else // Q_CC_MSVC +#if 0 +#pragma qt_sync_stop_processing +#endif //////////////////////////////////////////////////////////////////////////////////////////////////// @@ -74,7 +73,7 @@ # include // It's safer to remove the volatile and let the compiler add it as needed. -# define QT_INTERLOCKED_NO_VOLATILE +# define QT_INTERLOCKED_VOLATILE # else // _WIN32_WCE >= 0x600 || !_X86_ @@ -87,7 +86,7 @@ # define QT_INTERLOCKED_INTRINSIC # endif # else -# define QT_INTERLOCKED_NO_VOLATILE +# define QT_INTERLOCKED_VOLATILE # endif # endif // _WIN32_WCE >= 0x600 || !_X86_ @@ -111,12 +110,8 @@ QT_INTERLOCKED_CONCAT( \ QT_INTERLOCKED_CONCAT(QT_INTERLOCKED_PREFIX, Interlocked), name) -#ifdef QT_INTERLOCKED_NO_VOLATILE -# define QT_INTERLOCKED_VOLATILE -# define QT_INTERLOCKED_REMOVE_VOLATILE(a) qt_interlocked_remove_volatile(a) -#else +#ifndef QT_INTERLOCKED_VOLATILE # define QT_INTERLOCKED_VOLATILE volatile -# define QT_INTERLOCKED_REMOVE_VOLATILE(a) a #endif #ifndef QT_INTERLOCKED_PREFIX @@ -173,297 +168,194 @@ extern "C" { // Interlocked* replacement macros #define QT_INTERLOCKED_INCREMENT(value) \ - QT_INTERLOCKED_FUNCTION( Increment )( \ - QT_INTERLOCKED_REMOVE_VOLATILE( value ) ) + QT_INTERLOCKED_FUNCTION(Increment)(value) #define QT_INTERLOCKED_DECREMENT(value) \ - QT_INTERLOCKED_FUNCTION( Decrement )( \ - QT_INTERLOCKED_REMOVE_VOLATILE( value ) ) + QT_INTERLOCKED_FUNCTION(Decrement)(value) #define QT_INTERLOCKED_COMPARE_EXCHANGE(value, newValue, expectedValue) \ - QT_INTERLOCKED_FUNCTION( CompareExchange )( \ - QT_INTERLOCKED_REMOVE_VOLATILE( value ), \ - newValue, \ - expectedValue ) + QT_INTERLOCKED_FUNCTION(CompareExchange)((value), (newValue), (expectedValue)) #define QT_INTERLOCKED_EXCHANGE(value, newValue) \ - QT_INTERLOCKED_FUNCTION( Exchange )( \ - QT_INTERLOCKED_REMOVE_VOLATILE( value ), \ - newValue ) + QT_INTERLOCKED_FUNCTION(Exchange)((value), (newValue)) #define QT_INTERLOCKED_EXCHANGE_ADD(value, valueToAdd) \ - QT_INTERLOCKED_FUNCTION( ExchangeAdd )( \ - QT_INTERLOCKED_REMOVE_VOLATILE( value ), \ - valueToAdd ) + QT_INTERLOCKED_FUNCTION(ExchangeAdd)((value), (valueToAdd)) #if defined(Q_OS_WINCE) || defined(__i386__) || defined(_M_IX86) # define QT_INTERLOCKED_COMPARE_EXCHANGE_POINTER(value, newValue, expectedValue) \ reinterpret_cast( \ - QT_INTERLOCKED_FUNCTION( CompareExchange )( \ - QT_INTERLOCKED_REMOVE_VOLATILE( value ## _integral ), \ - (long)( newValue ), \ - (long)( expectedValue ) )) + QT_INTERLOCKED_FUNCTION(CompareExchange)( \ + reinterpret_cast(value), \ + long(newValue), \ + long(expectedValue))) # define QT_INTERLOCKED_EXCHANGE_POINTER(value, newValue) \ - QT_INTERLOCKED_FUNCTION( Exchange )( \ - QT_INTERLOCKED_REMOVE_VOLATILE( value ## _integral ), \ - (quintptr)( newValue ) ) + QT_INTERLOCKED_FUNCTION(Exchange)( \ + reinterpret_cast(value), \ + long(newValue)) # define QT_INTERLOCKED_EXCHANGE_ADD_POINTER(value, valueToAdd) \ - QT_INTERLOCKED_FUNCTION( ExchangeAdd )( \ - QT_INTERLOCKED_REMOVE_VOLATILE( value ## _integral ), \ - valueToAdd ) + QT_INTERLOCKED_FUNCTION(ExchangeAdd)( \ + reinterpret_cast(value), \ + (valueToAdd)) #else // !defined(Q_OS_WINCE) && !defined(__i386__) && !defined(_M_IX86) # define QT_INTERLOCKED_COMPARE_EXCHANGE_POINTER(value, newValue, expectedValue) \ - QT_INTERLOCKED_FUNCTION( CompareExchangePointer )( \ - (void * QT_INTERLOCKED_VOLATILE *)( QT_INTERLOCKED_REMOVE_VOLATILE(value) ), \ - newValue, \ - expectedValue ) + QT_INTERLOCKED_FUNCTION(CompareExchangePointer)( \ + (void * QT_INTERLOCKED_VOLATILE *)(value), \ + (void *) (newValue), \ + (void *) (expectedValue)) # define QT_INTERLOCKED_EXCHANGE_POINTER(value, newValue) \ - QT_INTERLOCKED_FUNCTION( ExchangePointer )( \ - (void * QT_INTERLOCKED_VOLATILE *)( QT_INTERLOCKED_REMOVE_VOLATILE(value) ), \ - newValue ) + QT_INTERLOCKED_FUNCTION(ExchangePointer)( \ + (void * QT_INTERLOCKED_VOLATILE *)(value), \ + (void *) (newValue)) # define QT_INTERLOCKED_EXCHANGE_ADD_POINTER(value, valueToAdd) \ - QT_INTERLOCKED_FUNCTION( ExchangeAdd64 )( \ - QT_INTERLOCKED_REMOVE_VOLATILE( value ## _integral ), \ - valueToAdd ) + QT_INTERLOCKED_FUNCTION(ExchangeAdd64)( \ + reinterpret_cast(value), \ + (valueToAdd)) #endif // !defined(Q_OS_WINCE) && !defined(__i386__) && !defined(_M_IX86) //////////////////////////////////////////////////////////////////////////////////////////////////// -QT_BEGIN_HEADER - -QT_BEGIN_NAMESPACE - #define Q_ATOMIC_INT_REFERENCE_COUNTING_IS_ALWAYS_NATIVE #define Q_ATOMIC_INT_REFERENCE_COUNTING_IS_WAIT_FREE -inline bool QBasicAtomicInt::isReferenceCountingNative() -{ return true; } -inline bool QBasicAtomicInt::isReferenceCountingWaitFree() -{ return true; } - #define Q_ATOMIC_INT_TEST_AND_SET_IS_ALWAYS_NATIVE #define Q_ATOMIC_INT_TEST_AND_SET_IS_WAIT_FREE -inline bool QBasicAtomicInt::isTestAndSetNative() -{ return true; } -inline bool QBasicAtomicInt::isTestAndSetWaitFree() -{ return true; } - #define Q_ATOMIC_INT_FETCH_AND_STORE_IS_ALWAYS_NATIVE #define Q_ATOMIC_INT_FETCH_AND_STORE_IS_WAIT_FREE -inline bool QBasicAtomicInt::isFetchAndStoreNative() -{ return true; } -inline bool QBasicAtomicInt::isFetchAndStoreWaitFree() -{ return true; } - #define Q_ATOMIC_INT_FETCH_AND_ADD_IS_ALWAYS_NATIVE #define Q_ATOMIC_INT_FETCH_AND_ADD_IS_WAIT_FREE -inline bool QBasicAtomicInt::isFetchAndAddNative() -{ return true; } -inline bool QBasicAtomicInt::isFetchAndAddWaitFree() -{ return true; } +#define Q_ATOMIC_INT32_IS_SUPPORTED + +#define Q_ATOMIC_INT32_REFERENCE_COUNTING_IS_ALWAYS_NATIVE +#define Q_ATOMIC_INT32_REFERENCE_COUNTING_IS_WAIT_FREE + +#define Q_ATOMIC_INT32_TEST_AND_SET_IS_ALWAYS_NATIVE +#define Q_ATOMIC_INT32_TEST_AND_SET_IS_WAIT_FREE + +#define Q_ATOMIC_INT32_FETCH_AND_STORE_IS_ALWAYS_NATIVE +#define Q_ATOMIC_INT32_FETCH_AND_STORE_IS_WAIT_FREE + +#define Q_ATOMIC_INT32_FETCH_AND_ADD_IS_ALWAYS_NATIVE +#define Q_ATOMIC_INT32_FETCH_AND_ADD_IS_WAIT_FREE #define Q_ATOMIC_POINTER_TEST_AND_SET_IS_ALWAYS_NATIVE #define Q_ATOMIC_POINTER_TEST_AND_SET_IS_WAIT_FREE -template -Q_INLINE_TEMPLATE bool QBasicAtomicPointer::isTestAndSetNative() -{ return true; } -template -Q_INLINE_TEMPLATE bool QBasicAtomicPointer::isTestAndSetWaitFree() -{ return true; } - #define Q_ATOMIC_POINTER_FETCH_AND_STORE_IS_ALWAYS_NATIVE #define Q_ATOMIC_POINTER_FETCH_AND_STORE_IS_WAIT_FREE -template -Q_INLINE_TEMPLATE bool QBasicAtomicPointer::isFetchAndStoreNative() -{ return true; } -template -Q_INLINE_TEMPLATE bool QBasicAtomicPointer::isFetchAndStoreWaitFree() -{ return true; } - #define Q_ATOMIC_POINTER_FETCH_AND_ADD_IS_ALWAYS_NATIVE #define Q_ATOMIC_POINTER_FETCH_AND_ADD_IS_WAIT_FREE -template -Q_INLINE_TEMPLATE bool QBasicAtomicPointer::isFetchAndAddNative() -{ return true; } -template -Q_INLINE_TEMPLATE bool QBasicAtomicPointer::isFetchAndAddWaitFree() -{ return true; } //////////////////////////////////////////////////////////////////////////////////////////////////// -#ifdef QT_INTERLOCKED_NO_VOLATILE -template -Q_INLINE_TEMPLATE T *qt_interlocked_remove_volatile(T volatile *t) +template<> struct QAtomicIntegerTraits { enum { IsInteger = 1 }; }; +template<> struct QAtomicIntegerTraits { enum { IsInteger = 1 }; }; +template<> struct QAtomicIntegerTraits { enum { IsInteger = 1 }; }; +template<> struct QAtomicIntegerTraits { enum { IsInteger = 1 }; }; + +// No definition, needs specialization +template struct QAtomicOpsBySize; + +template <> +struct QAtomicOpsBySize<4> : QGenericAtomicOps > { - return const_cast(t); -} -#endif // !QT_INTERLOCKED_NO_VOLATILE + // The 32-bit Interlocked*() API takes paramters as longs. + typedef long Type; -//////////////////////////////////////////////////////////////////////////////////////////////////// + static inline bool isReferenceCountingNative() { return true; } + static inline bool isReferenceCountingWaitFree() { return true; } + static bool ref(long &_q_value); + static bool deref(long &_q_value); -inline bool QBasicAtomicInt::ref() + static inline bool isTestAndSetNative() { return true; } + static inline bool isTestAndSetWaitFree() { return true; } + static bool testAndSetRelaxed(long &_q_value, long expectedValue, long newValue); + + static inline bool isFetchAndStoreNative() { return true; } + static inline bool isFetchAndStoreWaitFree() { return true; } + static long fetchAndStoreRelaxed(long &_q_value, long newValue); + + static inline bool isFetchAndAddNative() { return true; } + static inline bool isFetchAndAddWaitFree() { return true; } + static long fetchAndAddRelaxed(long &_q_value, QAtomicAdditiveType::AdditiveT valueToAdd); +}; + +template +struct QAtomicOps : QAtomicOpsBySize +{ }; + +inline bool QAtomicOpsBySize<4>::ref(long &_q_value) { return QT_INTERLOCKED_INCREMENT(&_q_value) != 0; } -inline bool QBasicAtomicInt::deref() +inline bool QAtomicOpsBySize<4>::deref(long &_q_value) { return QT_INTERLOCKED_DECREMENT(&_q_value) != 0; } -inline bool QBasicAtomicInt::testAndSetOrdered(int expectedValue, int newValue) +inline bool QAtomicOpsBySize<4>::testAndSetRelaxed(long &_q_value, long expectedValue, long newValue) { - return QT_INTERLOCKED_COMPARE_EXCHANGE(&_q_value, newValue, expectedValue) - == expectedValue; + return QT_INTERLOCKED_COMPARE_EXCHANGE(&_q_value, newValue, expectedValue) == expectedValue; } -inline int QBasicAtomicInt::fetchAndStoreOrdered(int newValue) +inline long QAtomicOpsBySize<4>::fetchAndStoreRelaxed(long &_q_value, long newValue) { return QT_INTERLOCKED_EXCHANGE(&_q_value, newValue); } -inline int QBasicAtomicInt::fetchAndAddOrdered(int valueToAdd) +inline long QAtomicOpsBySize<4>::fetchAndAddRelaxed(long &_q_value, QAtomicAdditiveType::AdditiveT valueToAdd) { - return QT_INTERLOCKED_EXCHANGE_ADD(&_q_value, valueToAdd); + return QT_INTERLOCKED_EXCHANGE_ADD(&_q_value, valueToAdd * QAtomicAdditiveType::AddScale); } -//////////////////////////////////////////////////////////////////////////////////////////////////// +// Specialization for pointer types, since we have Interlocked*Pointer() variants in some configurations +template +struct QAtomicOps : QGenericAtomicOps > +{ + typedef T *Type; + + static inline bool isTestAndSetNative() { return true; } + static inline bool isTestAndSetWaitFree() { return true; } + static bool testAndSetRelaxed(T *&_q_value, T *expectedValue, T *newValue); + + static inline bool isFetchAndStoreNative() { return true; } + static inline bool isFetchAndStoreWaitFree() { return true; } + static T *fetchAndStoreRelaxed(T *&_q_value, T *newValue); + + static inline bool isFetchAndAddNative() { return true; } + static inline bool isFetchAndAddWaitFree() { return true; } + static T *fetchAndAddRelaxed(T *&_q_value, qptrdiff valueToAdd); +}; template -Q_INLINE_TEMPLATE bool QBasicAtomicPointer::testAndSetOrdered(T *expectedValue, T *newValue) +inline bool QAtomicOps::testAndSetRelaxed(T *&_q_value, T *expectedValue, T *newValue) { - return QT_INTERLOCKED_COMPARE_EXCHANGE_POINTER(&_q_value, (void*)newValue, (void*)expectedValue) - == expectedValue; + return QT_INTERLOCKED_COMPARE_EXCHANGE_POINTER(&_q_value, newValue, expectedValue) == expectedValue; } template -Q_INLINE_TEMPLATE T *QBasicAtomicPointer::fetchAndStoreOrdered(T* newValue) +inline T *QAtomicOps::fetchAndStoreRelaxed(T *&_q_value, T *newValue) { - return reinterpret_cast( - QT_INTERLOCKED_EXCHANGE_POINTER(&_q_value, (void*)newValue)); + return reinterpret_cast(QT_INTERLOCKED_EXCHANGE_POINTER(&_q_value, newValue)); } template -Q_INLINE_TEMPLATE T *QBasicAtomicPointer::fetchAndAddOrdered(qptrdiff valueToAdd) +inline T *QAtomicOps::fetchAndAddRelaxed(T *&_q_value, qptrdiff valueToAdd) { - return reinterpret_cast( - QT_INTERLOCKED_EXCHANGE_ADD_POINTER(&_q_value, valueToAdd * sizeof(T))); -} - -//////////////////////////////////////////////////////////////////////////////////////////////////// - -inline bool QBasicAtomicInt::testAndSetRelaxed(int expectedValue, int newValue) -{ - return testAndSetOrdered(expectedValue, newValue); -} - -inline bool QBasicAtomicInt::testAndSetAcquire(int expectedValue, int newValue) -{ - return testAndSetOrdered(expectedValue, newValue); -} - -inline bool QBasicAtomicInt::testAndSetRelease(int expectedValue, int newValue) -{ - return testAndSetOrdered(expectedValue, newValue); -} - -inline int QBasicAtomicInt::fetchAndStoreRelaxed(int newValue) -{ - return fetchAndStoreOrdered(newValue); -} - -inline int QBasicAtomicInt::fetchAndStoreAcquire(int newValue) -{ - return fetchAndStoreOrdered(newValue); -} - -inline int QBasicAtomicInt::fetchAndStoreRelease(int newValue) -{ - return fetchAndStoreOrdered(newValue); -} - -inline int QBasicAtomicInt::fetchAndAddRelaxed(int valueToAdd) -{ - return fetchAndAddOrdered(valueToAdd); -} - -inline int QBasicAtomicInt::fetchAndAddAcquire(int valueToAdd) -{ - return fetchAndAddOrdered(valueToAdd); -} - -inline int QBasicAtomicInt::fetchAndAddRelease(int valueToAdd) -{ - return fetchAndAddOrdered(valueToAdd); -} - -//////////////////////////////////////////////////////////////////////////////////////////////////// - -template -Q_INLINE_TEMPLATE bool QBasicAtomicPointer::testAndSetRelaxed(T *expectedValue, T *newValue) -{ - return testAndSetOrdered(expectedValue, newValue); -} - -template -Q_INLINE_TEMPLATE bool QBasicAtomicPointer::testAndSetAcquire(T *expectedValue, T *newValue) -{ - return testAndSetOrdered(expectedValue, newValue); -} - -template -Q_INLINE_TEMPLATE bool QBasicAtomicPointer::testAndSetRelease(T *expectedValue, T *newValue) -{ - return testAndSetOrdered(expectedValue, newValue); -} - -template -Q_INLINE_TEMPLATE T *QBasicAtomicPointer::fetchAndStoreRelaxed(T *newValue) -{ - return fetchAndStoreOrdered(newValue); -} - -template -Q_INLINE_TEMPLATE T *QBasicAtomicPointer::fetchAndStoreAcquire(T *newValue) -{ - return fetchAndStoreOrdered(newValue); -} - -template -Q_INLINE_TEMPLATE T *QBasicAtomicPointer::fetchAndStoreRelease(T *newValue) -{ - return fetchAndStoreOrdered(newValue); -} - -template -Q_INLINE_TEMPLATE T *QBasicAtomicPointer::fetchAndAddRelaxed(qptrdiff valueToAdd) -{ - return fetchAndAddOrdered(valueToAdd); -} - -template -Q_INLINE_TEMPLATE T *QBasicAtomicPointer::fetchAndAddAcquire(qptrdiff valueToAdd) -{ - return fetchAndAddOrdered(valueToAdd); -} - -template -Q_INLINE_TEMPLATE T *QBasicAtomicPointer::fetchAndAddRelease(qptrdiff valueToAdd) -{ - return fetchAndAddOrdered(valueToAdd); + return reinterpret_cast(QT_INTERLOCKED_EXCHANGE_ADD_POINTER(&_q_value, valueToAdd * sizeof(T))); } //////////////////////////////////////////////////////////////////////////////////////////////////// @@ -474,9 +366,7 @@ Q_INLINE_TEMPLATE T *QBasicAtomicPointer::fetchAndAddRelease(qptrdiff valueTo #undef QT_INTERLOCKED_FUNCTION #undef QT_INTERLOCKED_PREFIX -#undef QT_INTERLOCKED_NO_VOLATILE #undef QT_INTERLOCKED_VOLATILE -#undef QT_INTERLOCKED_REMOVE_VOLATILE #undef QT_INTERLOCKED_INCREMENT #undef QT_INTERLOCKED_DECREMENT @@ -488,7 +378,6 @@ Q_INLINE_TEMPLATE T *QBasicAtomicPointer::fetchAndAddRelease(qptrdiff valueTo #undef QT_INTERLOCKED_EXCHANGE_ADD_POINTER QT_END_NAMESPACE - QT_END_HEADER #endif // Q_CC_MSVC diff --git a/src/corelib/thread/qbasicatomic.h b/src/corelib/thread/qbasicatomic.h index 3ef2d8a4cd..44f536724c 100644 --- a/src/corelib/thread/qbasicatomic.h +++ b/src/corelib/thread/qbasicatomic.h @@ -46,9 +46,8 @@ #if defined(QT_MOC) || defined(QT_BUILD_QMAKE) || defined(QT_RCC) || defined(QT_UIC) || defined(QT_BOOTSTRAPPED) # include -#elif defined(Q_CC_MSVC) - // not ported yet -# define QT_OLD_ATOMICS +#elif defined(Q_OS_WIN) && defined(Q_CC_MSVC) +# include #elif defined(__arm__) || defined(__TARGET_ARCH_ARM) # include #elif defined(__i386) || defined(__i386__) diff --git a/src/corelib/thread/qgenericatomic.h b/src/corelib/thread/qgenericatomic.h index a136e98adc..984ebed47b 100644 --- a/src/corelib/thread/qgenericatomic.h +++ b/src/corelib/thread/qgenericatomic.h @@ -86,8 +86,8 @@ template struct QGenericAtomicOps return _q_value; } - template static inline always_inline - void store(T &_q_value, T newValue) + template static inline always_inline + void store(T &_q_value, X newValue) { _q_value = newValue; } @@ -100,8 +100,8 @@ template struct QGenericAtomicOps return tmp; } - template static inline always_inline - void storeRelease(T &_q_value, T newValue) + template static inline always_inline + void storeRelease(T &_q_value, X newValue) { BaseClass::releaseMemoryFence(); *static_cast(&_q_value) = newValue; @@ -128,27 +128,27 @@ template struct QGenericAtomicOps // Archictectures must implement them static inline bool isTestAndSetNative(); static inline bool isTestAndSetWaitFree(); - template static inline - bool testAndSetRelaxed(T &_q_value, T expectedValue, T newValue); + template static inline + bool testAndSetRelaxed(T &_q_value, X expectedValue, X newValue); #endif - template static inline always_inline - bool testAndSetAcquire(T &_q_value, T expectedValue, T newValue) + template static inline always_inline + bool testAndSetAcquire(T &_q_value, X expectedValue, X newValue) { bool tmp = BaseClass::testAndSetRelaxed(_q_value, expectedValue, newValue); BaseClass::acquireMemoryFence(); return tmp; } - template static inline always_inline - bool testAndSetRelease(T &_q_value, T expectedValue, T newValue) + template static inline always_inline + bool testAndSetRelease(T &_q_value, X expectedValue, X newValue) { BaseClass::releaseMemoryFence(); return BaseClass::testAndSetRelaxed(_q_value, expectedValue, newValue); } - template static inline always_inline - bool testAndSetOrdered(T &_q_value, T expectedValue, T newValue) + template static inline always_inline + bool testAndSetOrdered(T &_q_value, X expectedValue, X newValue) { BaseClass::orderedMemoryFence(); return BaseClass::testAndSetRelaxed(_q_value, expectedValue, newValue); @@ -157,8 +157,8 @@ template struct QGenericAtomicOps static inline bool isFetchAndStoreNative() { return false; } static inline bool isFetchAndStoreWaitFree() { return false; } - template static inline always_inline - T fetchAndStoreRelaxed(T &_q_value, T newValue) + template static inline always_inline + T fetchAndStoreRelaxed(T &_q_value, X newValue) { // implement fetchAndStore on top of testAndSet Q_FOREVER { @@ -168,23 +168,23 @@ template struct QGenericAtomicOps } } - template static inline always_inline - T fetchAndStoreAcquire(T &_q_value, T newValue) + template static inline always_inline + T fetchAndStoreAcquire(T &_q_value, X newValue) { T tmp = BaseClass::fetchAndStoreRelaxed(_q_value, newValue); BaseClass::acquireMemoryFence(); return tmp; } - template static inline always_inline - T fetchAndStoreRelease(T &_q_value, T newValue) + template static inline always_inline + T fetchAndStoreRelease(T &_q_value, X newValue) { BaseClass::releaseMemoryFence(); return BaseClass::fetchAndStoreRelaxed(_q_value, newValue); } - template static inline always_inline - T fetchAndStoreOrdered(T &_q_value, T newValue) + template static inline always_inline + T fetchAndStoreOrdered(T &_q_value, X newValue) { BaseClass::orderedMemoryFence(); return BaseClass::fetchAndStoreRelaxed(_q_value, newValue);