Port the Windows atomic implementation to use QGenericAtomicOps

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<T> 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 <Friedemann.Kleint@nokia.com>
Reviewed-by: João Abecasis <joao.abecasis@nokia.com>
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
bb10
Bradley T. Hughes 2012-01-30 15:04:06 +01:00 committed by Qt by Nokia
parent f04756f3f5
commit 307c034973
3 changed files with 134 additions and 246 deletions

View File

@ -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 <QtCore/qgenericatomic.h>
# 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 <winbase.h>
// 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<void *>( \
QT_INTERLOCKED_FUNCTION( CompareExchange )( \
QT_INTERLOCKED_REMOVE_VOLATILE( value ## _integral ), \
(long)( newValue ), \
(long)( expectedValue ) ))
QT_INTERLOCKED_FUNCTION(CompareExchange)( \
reinterpret_cast<long QT_INTERLOCKED_VOLATILE *>(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<long QT_INTERLOCKED_VOLATILE *>(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<long QT_INTERLOCKED_VOLATILE *>(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<qint64 QT_INTERLOCKED_VOLATILE *>(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 <typename T>
Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isTestAndSetNative()
{ return true; }
template <typename T>
Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isTestAndSetWaitFree()
{ return true; }
#define Q_ATOMIC_POINTER_FETCH_AND_STORE_IS_ALWAYS_NATIVE
#define Q_ATOMIC_POINTER_FETCH_AND_STORE_IS_WAIT_FREE
template <typename T>
Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndStoreNative()
{ return true; }
template <typename T>
Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndStoreWaitFree()
{ return true; }
#define Q_ATOMIC_POINTER_FETCH_AND_ADD_IS_ALWAYS_NATIVE
#define Q_ATOMIC_POINTER_FETCH_AND_ADD_IS_WAIT_FREE
template <typename T>
Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndAddNative()
{ return true; }
template <typename T>
Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndAddWaitFree()
{ return true; }
////////////////////////////////////////////////////////////////////////////////////////////////////
#ifdef QT_INTERLOCKED_NO_VOLATILE
template <class T>
Q_INLINE_TEMPLATE T *qt_interlocked_remove_volatile(T volatile *t)
template<> struct QAtomicIntegerTraits<int> { enum { IsInteger = 1 }; };
template<> struct QAtomicIntegerTraits<unsigned int> { enum { IsInteger = 1 }; };
template<> struct QAtomicIntegerTraits<long> { enum { IsInteger = 1 }; };
template<> struct QAtomicIntegerTraits<unsigned long> { enum { IsInteger = 1 }; };
// No definition, needs specialization
template <int N> struct QAtomicOpsBySize;
template <>
struct QAtomicOpsBySize<4> : QGenericAtomicOps<QAtomicOpsBySize<4> >
{
return const_cast<T *>(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<long>::AdditiveT valueToAdd);
};
template <typename T>
struct QAtomicOps : QAtomicOpsBySize<sizeof(T)>
{ };
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<long>::AdditiveT valueToAdd)
{
return QT_INTERLOCKED_EXCHANGE_ADD(&_q_value, valueToAdd);
return QT_INTERLOCKED_EXCHANGE_ADD(&_q_value, valueToAdd * QAtomicAdditiveType<long>::AddScale);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
// Specialization for pointer types, since we have Interlocked*Pointer() variants in some configurations
template <typename T>
struct QAtomicOps<T *> : QGenericAtomicOps<QAtomicOps<T *> >
{
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 <typename T>
Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetOrdered(T *expectedValue, T *newValue)
inline bool QAtomicOps<T *>::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 <typename T>
Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreOrdered(T* newValue)
inline T *QAtomicOps<T *>::fetchAndStoreRelaxed(T *&_q_value, T *newValue)
{
return reinterpret_cast<T *>(
QT_INTERLOCKED_EXCHANGE_POINTER(&_q_value, (void*)newValue));
return reinterpret_cast<T *>(QT_INTERLOCKED_EXCHANGE_POINTER(&_q_value, newValue));
}
template <typename T>
Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddOrdered(qptrdiff valueToAdd)
inline T *QAtomicOps<T *>::fetchAndAddRelaxed(T *&_q_value, qptrdiff valueToAdd)
{
return reinterpret_cast<T *>(
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 <typename T>
Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelaxed(T *expectedValue, T *newValue)
{
return testAndSetOrdered(expectedValue, newValue);
}
template <typename T>
Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetAcquire(T *expectedValue, T *newValue)
{
return testAndSetOrdered(expectedValue, newValue);
}
template <typename T>
Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelease(T *expectedValue, T *newValue)
{
return testAndSetOrdered(expectedValue, newValue);
}
template <typename T>
Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreRelaxed(T *newValue)
{
return fetchAndStoreOrdered(newValue);
}
template <typename T>
Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreAcquire(T *newValue)
{
return fetchAndStoreOrdered(newValue);
}
template <typename T>
Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreRelease(T *newValue)
{
return fetchAndStoreOrdered(newValue);
}
template <typename T>
Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddRelaxed(qptrdiff valueToAdd)
{
return fetchAndAddOrdered(valueToAdd);
}
template <typename T>
Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddAcquire(qptrdiff valueToAdd)
{
return fetchAndAddOrdered(valueToAdd);
}
template <typename T>
Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddRelease(qptrdiff valueToAdd)
{
return fetchAndAddOrdered(valueToAdd);
return reinterpret_cast<T *>(QT_INTERLOCKED_EXCHANGE_ADD_POINTER(&_q_value, valueToAdd * sizeof(T)));
}
////////////////////////////////////////////////////////////////////////////////////////////////////
@ -474,9 +366,7 @@ Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::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<T>::fetchAndAddRelease(qptrdiff valueTo
#undef QT_INTERLOCKED_EXCHANGE_ADD_POINTER
QT_END_NAMESPACE
QT_END_HEADER
#endif // Q_CC_MSVC

View File

@ -46,9 +46,8 @@
#if defined(QT_MOC) || defined(QT_BUILD_QMAKE) || defined(QT_RCC) || defined(QT_UIC) || defined(QT_BOOTSTRAPPED)
# include <QtCore/qatomic_bootstrap.h>
#elif defined(Q_CC_MSVC)
// not ported yet
# define QT_OLD_ATOMICS
#elif defined(Q_OS_WIN) && defined(Q_CC_MSVC)
# include <QtCore/qatomic_windows.h>
#elif defined(__arm__) || defined(__TARGET_ARCH_ARM)
# include <QtCore/qatomic_arm.h>
#elif defined(__i386) || defined(__i386__)

View File

@ -86,8 +86,8 @@ template <typename BaseClass> struct QGenericAtomicOps
return _q_value;
}
template <typename T> static inline always_inline
void store(T &_q_value, T newValue)
template <typename T, typename X> static inline always_inline
void store(T &_q_value, X newValue)
{
_q_value = newValue;
}
@ -100,8 +100,8 @@ template <typename BaseClass> struct QGenericAtomicOps
return tmp;
}
template <typename T> static inline always_inline
void storeRelease(T &_q_value, T newValue)
template <typename T, typename X> static inline always_inline
void storeRelease(T &_q_value, X newValue)
{
BaseClass::releaseMemoryFence();
*static_cast<volatile T *>(&_q_value) = newValue;
@ -128,27 +128,27 @@ template <typename BaseClass> struct QGenericAtomicOps
// Archictectures must implement them
static inline bool isTestAndSetNative();
static inline bool isTestAndSetWaitFree();
template <typename T> static inline
bool testAndSetRelaxed(T &_q_value, T expectedValue, T newValue);
template <typename T, typename X> static inline
bool testAndSetRelaxed(T &_q_value, X expectedValue, X newValue);
#endif
template <typename T> static inline always_inline
bool testAndSetAcquire(T &_q_value, T expectedValue, T newValue)
template <typename T, typename X> 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 <typename T> static inline always_inline
bool testAndSetRelease(T &_q_value, T expectedValue, T newValue)
template <typename T, typename X> static inline always_inline
bool testAndSetRelease(T &_q_value, X expectedValue, X newValue)
{
BaseClass::releaseMemoryFence();
return BaseClass::testAndSetRelaxed(_q_value, expectedValue, newValue);
}
template <typename T> static inline always_inline
bool testAndSetOrdered(T &_q_value, T expectedValue, T newValue)
template <typename T, typename X> 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 <typename BaseClass> struct QGenericAtomicOps
static inline bool isFetchAndStoreNative() { return false; }
static inline bool isFetchAndStoreWaitFree() { return false; }
template <typename T> static inline always_inline
T fetchAndStoreRelaxed(T &_q_value, T newValue)
template <typename T, typename X> static inline always_inline
T fetchAndStoreRelaxed(T &_q_value, X newValue)
{
// implement fetchAndStore on top of testAndSet
Q_FOREVER {
@ -168,23 +168,23 @@ template <typename BaseClass> struct QGenericAtomicOps
}
}
template <typename T> static inline always_inline
T fetchAndStoreAcquire(T &_q_value, T newValue)
template <typename T, typename X> static inline always_inline
T fetchAndStoreAcquire(T &_q_value, X newValue)
{
T tmp = BaseClass::fetchAndStoreRelaxed(_q_value, newValue);
BaseClass::acquireMemoryFence();
return tmp;
}
template <typename T> static inline always_inline
T fetchAndStoreRelease(T &_q_value, T newValue)
template <typename T, typename X> static inline always_inline
T fetchAndStoreRelease(T &_q_value, X newValue)
{
BaseClass::releaseMemoryFence();
return BaseClass::fetchAndStoreRelaxed(_q_value, newValue);
}
template <typename T> static inline always_inline
T fetchAndStoreOrdered(T &_q_value, T newValue)
template <typename T, typename X> static inline always_inline
T fetchAndStoreOrdered(T &_q_value, X newValue)
{
BaseClass::orderedMemoryFence();
return BaseClass::fetchAndStoreRelaxed(_q_value, newValue);