diff options
author | João Abecasis <joao@abecasis.name> | 2009-08-31 15:05:51 (GMT) |
---|---|---|
committer | João Abecasis <joao@abecasis.name> | 2009-08-31 16:15:45 (GMT) |
commit | e70980b2aacbc758a0cd1e2246633278f7c505ab (patch) | |
tree | ee19500748f62181afbf424438c6ff03d12d7912 /src | |
parent | 06a4cdba05e4865d02a09a5633c31c462ac00014 (diff) | |
download | Qt-e70980b2aacbc758a0cd1e2246633278f7c505ab.zip Qt-e70980b2aacbc758a0cd1e2246633278f7c505ab.tar.gz Qt-e70980b2aacbc758a0cd1e2246633278f7c505ab.tar.bz2 |
Refactoring qatomic_windows.h
Consolidated Interlocked* declarations and API implementation through
macro hackery, (hopefully) for improved readability and maintainability.
Fixes anti-aliasing warnings with MinGW in qatomic_windows.h. Gcc
builds now use inline assembly for atomic operations, instead of relying
on Interlocked* functions which aren't consistently declared across
implementations (mingw32, mingw-w64, wine... others?).
Drops support for VC 6 and MetroWerks.
Reviewed-by: Thiago Macieira
Diffstat (limited to 'src')
-rw-r--r-- | src/corelib/arch/arch.pri | 3 | ||||
-rw-r--r-- | src/corelib/arch/qatomic_windows.h | 558 | ||||
-rw-r--r-- | src/corelib/thread/qbasicatomic.h | 15 |
3 files changed, 253 insertions, 323 deletions
diff --git a/src/corelib/arch/arch.pri b/src/corelib/arch/arch.pri index a25027b..57bc80a 100644 --- a/src/corelib/arch/arch.pri +++ b/src/corelib/arch/arch.pri @@ -1,6 +1,9 @@ win32:HEADERS += arch/qatomic_windows.h \ arch/qatomic_generic.h +win32-g++*:HEADERS += arch/qatomic_i386.h \ + arch/qatomic_x86_64.h + mac:HEADERS += arch/qatomic_macosx.h \ arch/qatomic_generic.h diff --git a/src/corelib/arch/qatomic_windows.h b/src/corelib/arch/qatomic_windows.h index a826bd3..50dedc1 100644 --- a/src/corelib/arch/qatomic_windows.h +++ b/src/corelib/arch/qatomic_windows.h @@ -42,6 +42,195 @@ #ifndef QATOMIC_WINDOWS_H #define QATOMIC_WINDOWS_H +#ifndef Q_CC_MSVC + +// Mingw and other GCC platforms get inline assembly + +# ifdef __i386__ +# include "QtCore/qatomic_i386.h" +# else +# include "QtCore/qatomic_x86_64.h" +# endif + +#else // Q_CC_MSVC + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +#ifndef Q_OS_WINCE + +// use compiler intrinsics for all atomic functions +# define QT_INTERLOCKED_PREFIX _ +# define QT_INTERLOCKED_PROTOTYPE __cdecl +# define QT_INTERLOCKED_DECLARE_PROTOTYPES +# define QT_INTERLOCKED_INTRINSIC + +#else // Q_OS_WINCE + +# if _WIN32_WCE < 0x600 && defined(_X86_) +// For X86 Windows CE, include winbase.h to catch inline functions which +// overwrite the regular definitions inside of coredll.dll. +// Though one could use the original version of Increment/Decrement, others are +// not exported at all. +# include <winbase.h> + +// It's safer to remove the volatile and let the compiler add it as needed. +# define QT_INTERLOCKED_NO_VOLATILE + +# else // _WIN32_WCE >= 0x600 || _X86_ + +# define QT_INTERLOCKED_PROTOTYPE __cdecl +# define QT_INTERLOCKED_DECLARE_PROTOTYPES + +# if _WIN32_WCE >= 0x600 && defined(_X86_) +# define QT_INTERLOCKED_PREFIX _ +# define QT_INTERLOCKED_INTRINSIC +# else +# define QT_INTERLOCKED_NO_VOLATILE +# endif + +# endif // _WIN32_WCE >= 0x600 || _X86_ + +#endif // Q_OS_WINCE + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// Prototype declaration + +#define QT_INTERLOCKED_CONCAT_I(prefix, suffix) \ + prefix ## suffix +#define QT_INTERLOCKED_CONCAT(prefix, suffix) \ + QT_INTERLOCKED_CONCAT_I(prefix, suffix) + +// MSVC intrinsics prefix function names with an underscore +#define QT_INTERLOCKED_FUNCTION(name) \ + QT_INTERLOCKED_CONCAT(QT_INTERLOCKED_PREFIX, name) + +#ifdef QT_INTERLOCKED_NO_VOLATILE +# define QT_INTERLOCKED_VOLATILE +# define QT_INTERLOCKED_REMOVE_VOLATILE(a) qt_interlocked_remove_volatile(a) +#else +# define QT_INTERLOCKED_VOLATILE volatile +# define QT_INTERLOCKED_REMOVE_VOLATILE(a) a +#endif + +#ifndef QT_INTERLOCKED_PREFIX +#define QT_INTERLOCKED_PREFIX +#endif + +#ifndef QT_INTERLOCKED_PROTOTYPE +#define QT_INTERLOCKED_PROTOTYPE +#endif + +#ifdef QT_INTERLOCKED_DECLARE_PROTOTYPES +#undef QT_INTERLOCKED_DECLARE_PROTOTYPES + +extern "C" { + + long QT_INTERLOCKED_PROTOTYPE QT_INTERLOCKED_FUNCTION( InterlockedIncrement )(long QT_INTERLOCKED_VOLATILE *); + long QT_INTERLOCKED_PROTOTYPE QT_INTERLOCKED_FUNCTION( InterlockedDecrement )(long QT_INTERLOCKED_VOLATILE *); + long QT_INTERLOCKED_PROTOTYPE QT_INTERLOCKED_FUNCTION( InterlockedCompareExchange )(long QT_INTERLOCKED_VOLATILE *, long, long); + long QT_INTERLOCKED_PROTOTYPE QT_INTERLOCKED_FUNCTION( InterlockedExchange )(long QT_INTERLOCKED_VOLATILE *, long); + long QT_INTERLOCKED_PROTOTYPE QT_INTERLOCKED_FUNCTION( InterlockedExchangeAdd )(long QT_INTERLOCKED_VOLATILE *, long); + +# if !defined(__i386__) && !defined(_M_IX86) + long QT_INTERLOCKED_FUNCTION( InterlockedCompareExchangePointer )(void * QT_INTERLOCKED_VOLATILE *, void *, void *); + long QT_INTERLOCKED_FUNCTION( InterlockedExchangePointer )(void * QT_INTERLOCKED_VOLATILE *, void *); + __int64 QT_INTERLOCKED_FUNCTION( InterlockedExchangeAdd64 )(__int64 QT_INTERLOCKED_VOLATILE *, long); +# endif + +} + +#endif // QT_INTERLOCKED_DECLARE_PROTOTYPES + +#undef QT_INTERLOCKED_PROTOTYPE +#undef QT_INTERLOCKED_VOLATILE + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef QT_INTERLOCKED_INTRINSIC +#undef QT_INTERLOCKED_INTRINSIC + +# pragma intrinsic (_InterlockedIncrement) +# pragma intrinsic (_InterlockedDecrement) +# pragma intrinsic (_InterlockedExchange) +# pragma intrinsic (_InterlockedCompareExchange) +# pragma intrinsic (_InterlockedExchangeAdd) + +# ifndef _M_IX86 +# pragma intrinsic (_InterlockedCompareExchangePointer) +# pragma intrinsic (_InterlockedExchangePointer) +# pragma intrinsic (_InterlockedExchangeAdd64) +# endif + +#endif // QT_INTERLOCKED_INTRINSIC + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// Interlocked* replacement macros + +#define QT_INTERLOCKED_INCREMENT(value) \ + QT_INTERLOCKED_FUNCTION(InterlockedIncrement)( \ + QT_INTERLOCKED_REMOVE_VOLATILE( value ) ) + +#define QT_INTERLOCKED_DECREMENT(value) \ + QT_INTERLOCKED_FUNCTION(InterlockedDecrement)( \ + QT_INTERLOCKED_REMOVE_VOLATILE( value ) ) + +#define QT_INTERLOCKED_COMPARE_EXCHANGE(value, newValue, expectedValue) \ + QT_INTERLOCKED_FUNCTION(InterlockedCompareExchange)( \ + QT_INTERLOCKED_REMOVE_VOLATILE( value ), \ + newValue, \ + expectedValue ) + +#define QT_INTERLOCKED_EXCHANGE(value, newValue) \ + QT_INTERLOCKED_FUNCTION(InterlockedExchange)( \ + QT_INTERLOCKED_REMOVE_VOLATILE( value ), \ + newValue ) + +#define QT_INTERLOCKED_EXCHANGE_ADD(value, valueToAdd) \ + QT_INTERLOCKED_FUNCTION(InterlockedExchangeAdd)( \ + QT_INTERLOCKED_REMOVE_VOLATILE( value ), \ + valueToAdd ) + +#if defined(__i386__) || defined(_M_IX86) + +# define QT_INTERLOCKED_COMPARE_EXCHANGE_POINTER(value, newValue, expectedValue) \ + reinterpret_cast<void *>( \ + QT_INTERLOCKED_FUNCTION(InterlockedCompareExchange)( \ + QT_INTERLOCKED_REMOVE_VOLATILE( value ## _integral ), \ + (long)( newValue ), \ + (long)( expectedValue ) )) + +# define QT_INTERLOCKED_EXCHANGE_POINTER(value, newValue) \ + QT_INTERLOCKED_FUNCTION(InterlockedExchange)( \ + QT_INTERLOCKED_REMOVE_VOLATILE( value ## _integral ), \ + (quintptr)( newValue ) ) + +# define QT_INTERLOCKED_EXCHANGE_ADD_POINTER(value, valueToAdd) \ + QT_INTERLOCKED_FUNCTION(InterlockedExchangeAdd)( \ + QT_INTERLOCKED_REMOVE_VOLATILE( value ## _integral ), \ + valueToAdd ) + +#else // !defined(__i386__) && !defined(_M_IX86) + +# define QT_INTERLOCKED_COMPARE_EXCHANGE_POINTER(value, newValue, expectedValue) \ + QT_INTERLOCKED_FUNCTION(InterlockedCompareExchangePointer)( \ + QT_INTERLOCKED_REMOVE_VOLATILE( value ), \ + newValue, \ + expectedValue ) + +# define QT_INTERLOCKED_EXCHANGE_POINTER(value, newValue) \ + QT_INTERLOCKED_FUNCTION(InterlockedExchangePointer)( \ + QT_INTERLOCKED_REMOVE_VOLATILE( value ), \ + newValue ) + +# define QT_INTERLOCKED_EXCHANGE_ADD_POINTER(value, valueToAdd) \ + QT_INTERLOCKED_FUNCTION(InterlockedExchangeAdd64)( \ + QT_INTERLOCKED_REMOVE_VOLATILE( value ## _integral ), \ + valueToAdd ) + +#endif // !defined(__i386__) && !defined(_M_IX86) + +//////////////////////////////////////////////////////////////////////////////////////////////////// + QT_BEGIN_HEADER QT_BEGIN_NAMESPACE @@ -107,369 +296,68 @@ template <typename T> Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndAddWaitFree() { return true; } -#if defined(Q_CC_MSVC) || defined(Q_CC_MWERKS) - -// MSVC++ 6.0 doesn't generate correct code when optimizations are turned on! -#if _MSC_VER < 1300 && defined (_M_IX86) - -inline bool QBasicAtomicInt::ref() -{ - volatile int *pointer = &_q_value; - unsigned char retVal; - __asm { - mov ECX,pointer - lock inc DWORD ptr[ECX] - setne retVal - } - return retVal != 0; -} - -inline bool QBasicAtomicInt::deref() -{ - volatile int *pointer = &_q_value; - unsigned char retVal; - __asm { - mov ECX,pointer - lock dec DWORD ptr[ECX] - setne retVal - } - return retVal != 0; -} - -inline bool QBasicAtomicInt::testAndSetOrdered(int expectedValue, int newValue) -{ - volatile int *pointer = &_q_value; - __asm { - mov EDX,pointer - mov EAX,expectedValue - mov ECX,newValue - lock cmpxchg dword ptr[EDX],ECX - mov newValue,EAX - } - return newValue == expectedValue; -} - - -inline int QBasicAtomicInt::fetchAndStoreOrdered(int newValue) -{ - volatile int *pointer = &_q_value; - __asm { - mov EDX,pointer - mov ECX,newValue - lock xchg dword ptr[EDX],ECX - mov newValue,ECX - } - return newValue; -} - - -inline int QBasicAtomicInt::fetchAndAddOrdered(int valueToAdd) -{ - volatile int *pointer = &_q_value; - __asm { - mov EDX,pointer - mov ECX,valueToAdd - lock xadd dword ptr[EDX],ECX - mov valueToAdd,ECX - } - return valueToAdd; -} +//////////////////////////////////////////////////////////////////////////////////////////////////// -template <typename T> -Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetOrdered(T *expectedValue, T *newValue) -{ - volatile void *pointer = &_q_value; - __asm { - mov EDX,pointer - mov EAX,expectedValue - mov ECX,newValue - lock cmpxchg dword ptr[EDX],ECX - mov newValue,EAX - } - return newValue == expectedValue; -} - -template <typename T> -Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreOrdered(T *newValue) -{ - volatile void *pointer = &_q_value; - __asm { - mov EDX,pointer - mov ECX,newValue - lock xchg dword ptr[EDX],ECX - mov newValue,ECX - } - return reinterpret_cast<T *>(newValue); -} - -template <typename T> -Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddOrdered(qptrdiff valueToAdd) +#ifdef QT_INTERLOCKED_NO_VOLATILE +template <class T> +Q_INLINE_TEMPLATE T *qt_interlocked_remove_volatile(T volatile *t) { - volatile void *pointer = &_q_value; - valueToAdd *= sizeof(T); - __asm { - mov EDX,pointer - mov ECX,valueToAdd - lock xadd dword ptr[EDX],ECX - mov pointer,ECX - } - return reinterpret_cast<T *>(const_cast<void *>(pointer)); + return const_cast<T *>(t); } +#endif // !QT_INTERLOCKED_NO_VOLATILE -#else - -#if !defined(Q_OS_WINCE) && !defined(Q_CC_MWERKS) -// use compiler intrinsics for all atomic functions -//those functions need to be define in the global namespace -QT_END_NAMESPACE - -extern "C" { - long __cdecl _InterlockedIncrement(volatile long *); - long __cdecl _InterlockedDecrement(volatile long *); - long __cdecl _InterlockedExchange(volatile long *, long); - long __cdecl _InterlockedCompareExchange(volatile long *, long, long); - long __cdecl _InterlockedExchangeAdd(volatile long *, long); -} -# pragma intrinsic (_InterlockedIncrement) -# pragma intrinsic (_InterlockedDecrement) -# pragma intrinsic (_InterlockedExchange) -# pragma intrinsic (_InterlockedCompareExchange) -# pragma intrinsic (_InterlockedExchangeAdd) - -# ifndef _M_IX86 -extern "C" { - void *_InterlockedCompareExchangePointer(void * volatile *, void *, void *); - void *_InterlockedExchangePointer(void * volatile *, void *); - __int64 _InterlockedExchangeAdd64(__int64 volatile * Addend, __int64 Value); -} -# pragma intrinsic (_InterlockedCompareExchangePointer) -# pragma intrinsic (_InterlockedExchangePointer) -# pragma intrinsic (_InterlockedExchangeAdd64) -# define _InterlockedExchangeAddPointer(a,b) \ - _InterlockedExchangeAdd64(reinterpret_cast<volatile __int64 *>(a), __int64(b)) -# else -# define _InterlockedCompareExchangePointer(a,b,c) \ - _InterlockedCompareExchange(reinterpret_cast<volatile long *>(a), long(b), long(c)) -# define _InterlockedExchangePointer(a, b) \ - _InterlockedExchange(reinterpret_cast<volatile long *>(a), long(b)) -# define _InterlockedExchangeAddPointer(a,b) \ - _InterlockedExchangeAdd(reinterpret_cast<volatile long *>(a), long(b)) -# endif - -QT_BEGIN_NAMESPACE +//////////////////////////////////////////////////////////////////////////////////////////////////// inline bool QBasicAtomicInt::ref() { - return _InterlockedIncrement(reinterpret_cast<volatile long *>(&_q_value)) != 0; + return QT_INTERLOCKED_INCREMENT(&_q_value) != 0; } inline bool QBasicAtomicInt::deref() { - return _InterlockedDecrement(reinterpret_cast<volatile long *>(&_q_value)) != 0; + return QT_INTERLOCKED_DECREMENT(&_q_value) != 0; } inline bool QBasicAtomicInt::testAndSetOrdered(int expectedValue, int newValue) { - return _InterlockedCompareExchange(reinterpret_cast<volatile long *>(&_q_value), newValue, expectedValue) == expectedValue; + return QT_INTERLOCKED_COMPARE_EXCHANGE(&_q_value, newValue, expectedValue) + == expectedValue; } inline int QBasicAtomicInt::fetchAndStoreOrdered(int newValue) { - return _InterlockedExchange(reinterpret_cast<volatile long *>(&_q_value), newValue); + return QT_INTERLOCKED_EXCHANGE(&_q_value, newValue); } inline int QBasicAtomicInt::fetchAndAddOrdered(int valueToAdd) { - return _InterlockedExchangeAdd(reinterpret_cast<volatile long *>(&_q_value), valueToAdd); + return QT_INTERLOCKED_EXCHANGE_ADD(&_q_value, valueToAdd); } -#if defined(Q_CC_MSVC) -#pragma warning( push ) -#pragma warning( disable : 4311 ) // ignoring the warning from /Wp64 -#endif +//////////////////////////////////////////////////////////////////////////////////////////////////// template <typename T> Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetOrdered(T *expectedValue, T *newValue) { - return (_InterlockedCompareExchangePointer(reinterpret_cast<void * volatile *>(&_q_value), - newValue, expectedValue) == -#ifndef _M_IX86 - (void *) -#else - (long) -#endif - (expectedValue)); -} - -#if defined(Q_CC_MSVC) -#pragma warning( pop ) -#endif - -template <typename T> -Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreOrdered(T *newValue) -{ - return reinterpret_cast<T *>(_InterlockedExchangePointer(reinterpret_cast<void * volatile *>(&_q_value), newValue)); + return QT_INTERLOCKED_COMPARE_EXCHANGE_POINTER(&_q_value, newValue, expectedValue) + == expectedValue; } template <typename T> -Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddOrdered(qptrdiff valueToAdd) -{ - return reinterpret_cast<T *>(_InterlockedExchangeAddPointer(reinterpret_cast<void * volatile *>(&_q_value), valueToAdd * sizeof(T))); -} - -#else // Q_OS_WINCE - -#if (_WIN32_WCE < 0x600 && defined(_X86_)) || defined(Q_CC_MWERKS) -// For X86 Windows CE build we need to include winbase.h to be able -// to catch the inline functions which overwrite the regular -// definitions inside of coredll.dll. Though one could use the -// original version of Increment/Decrement, the others are not -// exported at all. -#include <winbase.h> -#else -#if _WIN32_WCE >= 0x600 || defined(Q_CC_MWERKS) -#define Q_ARGUMENT_TYPE volatile -# if defined(_X86_) -# define InterlockedIncrement _InterlockedIncrement -# define InterlockedDecrement _InterlockedDecrement -# define InterlockedExchange _InterlockedExchange -# define InterlockedCompareExchange _InterlockedCompareExchange -# define InterlockedExchangeAdd _InterlockedExchangeAdd -# endif -#else -#define Q_ARGUMENT_TYPE -#endif - -QT_END_NAMESPACE - -extern "C" { -long __cdecl InterlockedIncrement(long Q_ARGUMENT_TYPE * lpAddend); -long __cdecl InterlockedDecrement(long Q_ARGUMENT_TYPE * lpAddend); -long __cdecl InterlockedExchange(long Q_ARGUMENT_TYPE * Target, long Value); -long __cdecl InterlockedCompareExchange(long Q_ARGUMENT_TYPE * Destination, long Exchange, long Comperand); -long __cdecl InterlockedExchangeAdd(long Q_ARGUMENT_TYPE * Addend, long Value); -} - -#if _WIN32_WCE >= 0x600 && defined(_X86_) -# pragma intrinsic (_InterlockedIncrement) -# pragma intrinsic (_InterlockedDecrement) -# pragma intrinsic (_InterlockedExchange) -# pragma intrinsic (_InterlockedCompareExchange) -# pragma intrinsic (_InterlockedExchangeAdd) -#endif - -QT_BEGIN_NAMESPACE - -#endif - - -inline bool QBasicAtomicInt::ref() -{ - return InterlockedIncrement((long*)(&_q_value)) != 0; -} - -inline bool QBasicAtomicInt::deref() -{ - return InterlockedDecrement((long*)(&_q_value)) != 0; -} - -inline bool QBasicAtomicInt::testAndSetOrdered(int expectedValue, int newValue) -{ - return InterlockedCompareExchange((long*)(&_q_value), newValue, expectedValue) == expectedValue; -} - -inline int QBasicAtomicInt::fetchAndStoreOrdered(int newValue) -{ - return InterlockedExchange((long*)(&_q_value), newValue); -} - -inline int QBasicAtomicInt::fetchAndAddOrdered(int valueToAdd) -{ - return InterlockedExchangeAdd((long*)(&_q_value), valueToAdd); -} - -template <typename T> -Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetOrdered(T *expectedValue, T *newValue) -{ - return (InterlockedCompareExchange((long*)(&_q_value), - (long)newValue, (long)expectedValue) == - (long)(expectedValue)); -} - -template <typename T> -Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreOrdered(T *newValue) +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreOrdered(T* newValue) { - return reinterpret_cast<T *>(InterlockedExchange((long*)(&_q_value), (long)newValue)); + return reinterpret_cast<T *>( + QT_INTERLOCKED_EXCHANGE_POINTER(&_q_value, newValue)); } template <typename T> Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddOrdered(qptrdiff valueToAdd) { - return reinterpret_cast<T *>(InterlockedExchangeAdd((long*)(&_q_value), valueToAdd * sizeof(T))); -} - -#endif //Q_OS_WINCE - -#endif // _MSC_VER ... - -#else - -// __INTERLOCKED_DECLARED is defined in MinGW's winbase.h. Simply, preferrably we use -// MinGW's definition, such that we pick up variations in the headers. -#ifndef __INTERLOCKED_DECLARED -#define __INTERLOCKED_DECLARED -QT_END_NAMESPACE - -extern "C" { - __declspec(dllimport) long __stdcall InterlockedCompareExchange(long *, long, long); - __declspec(dllimport) long __stdcall InterlockedIncrement(long *); - __declspec(dllimport) long __stdcall InterlockedDecrement(long *); - __declspec(dllimport) long __stdcall InterlockedExchange(long *, long); - __declspec(dllimport) long __stdcall InterlockedExchangeAdd(long *, long); -} - -QT_BEGIN_NAMESPACE -#endif - -inline bool QBasicAtomicInt::ref() -{ - return InterlockedIncrement(reinterpret_cast<long *>(const_cast<int *>(&_q_value))) != 0; -} - -inline bool QBasicAtomicInt::deref() -{ - return InterlockedDecrement(reinterpret_cast<long *>(const_cast<int *>(&_q_value))) != 0; + return reinterpret_cast<T *>( + QT_INTERLOCKED_EXCHANGE_ADD_POINTER(&_q_value, valueToAdd * sizeof(T))); } -inline bool QBasicAtomicInt::testAndSetOrdered(int expectedValue, int newValue) -{ - return InterlockedCompareExchange(reinterpret_cast<long *>(const_cast<int *>(&_q_value)), newValue, expectedValue) == expectedValue; -} - -inline int QBasicAtomicInt::fetchAndStoreOrdered(int newValue) -{ return InterlockedExchange(reinterpret_cast<long *>(const_cast<int *>(&_q_value)), newValue); } - -inline int QBasicAtomicInt::fetchAndAddOrdered(int valueToAdd) -{ - return InterlockedExchangeAdd(reinterpret_cast<long *>(const_cast<int *>(&_q_value)), valueToAdd); -} - -template <typename T> -Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetOrdered(T *expectedValue, T* newValue) -{ return InterlockedCompareExchange(reinterpret_cast<long *>(const_cast<T **>(&_q_value)), - reinterpret_cast<long>(newValue), - reinterpret_cast<long>(expectedValue)) == reinterpret_cast<long>(expectedValue); } - -template <typename T> -Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreOrdered(T* newValue) -{ return reinterpret_cast<T *>(InterlockedExchange(reinterpret_cast<long *>(const_cast<T **>(&_q_value)), - reinterpret_cast<long>(newValue))); } - -template <typename T> -Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddOrdered(qptrdiff valueToAdd) -{ return reinterpret_cast<T *>(InterlockedExchangeAdd(reinterpret_cast<long *>(const_cast<T **>(&_q_value)), valueToAdd * sizeof(T))); } - -#endif // Q_CC_GNU +//////////////////////////////////////////////////////////////////////////////////////////////////// inline bool QBasicAtomicInt::testAndSetRelaxed(int expectedValue, int newValue) { @@ -516,6 +404,8 @@ inline int QBasicAtomicInt::fetchAndAddRelease(int valueToAdd) return fetchAndAddOrdered(valueToAdd); } +//////////////////////////////////////////////////////////////////////////////////////////////////// + template <typename T> Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelaxed(T *expectedValue, T *newValue) { @@ -570,8 +460,30 @@ Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddRelease(qptrdiff valueTo return fetchAndAddOrdered(valueToAdd); } +//////////////////////////////////////////////////////////////////////////////////////////////////// +// Cleanup + +#undef QT_INTERLOCKED_CONCAT_I +#undef QT_INTERLOCKED_CONCAT +#undef QT_INTERLOCKED_FUNCTION +#undef QT_INTERLOCKED_PREFIX + +#undef QT_INTERLOCKED_NO_VOLATILE +#undef QT_INTERLOCKED_REMOVE_VOLATILE + +#undef QT_INTERLOCKED_INCREMENT +#undef QT_INTERLOCKED_DECREMENT +#undef QT_INTERLOCKED_COMPARE_EXCHANGE +#undef QT_INTERLOCKED_EXCHANGE +#undef QT_INTERLOCKED_EXCHANGE_ADD +#undef QT_INTERLOCKED_COMPARE_EXCHANGE_POINTER +#undef QT_INTERLOCKED_EXCHANGE_POINTER +#undef QT_INTERLOCKED_EXCHANGE_ADD_POINTER + QT_END_NAMESPACE QT_END_HEADER +#endif // Q_CC_MSVC + #endif // QATOMIC_WINDOWS_H diff --git a/src/corelib/thread/qbasicatomic.h b/src/corelib/thread/qbasicatomic.h index e96b4d2..629fb3d 100644 --- a/src/corelib/thread/qbasicatomic.h +++ b/src/corelib/thread/qbasicatomic.h @@ -56,7 +56,13 @@ public: #ifdef QT_ARCH_PARISC int _q_lock[4]; #endif +#if defined(QT_ARCH_WINDOWS) || defined(QT_ARCH_WINDOWSCE) + union { // needed for Q_BASIC_ATOMIC_INITIALIZER + volatile long _q_value; + }; +#else volatile int _q_value; +#endif // Non-atomic API inline bool operator==(int value) const @@ -128,7 +134,14 @@ public: #ifdef QT_ARCH_PARISC int _q_lock[4]; #endif +#if defined(QT_ARCH_WINDOWS) || defined(QT_ARCH_WINDOWSCE) + union { + T * volatile _q_value; + long volatile _q_value_integral; + }; +#else T * volatile _q_value; +#endif // Non-atomic API inline bool operator==(T *value) const @@ -194,6 +207,8 @@ public: #ifdef QT_ARCH_PARISC # define Q_BASIC_ATOMIC_INITIALIZER(a) {{-1,-1,-1,-1},(a)} +#elif defined(QT_ARCH_WINDOWS) || defined(QT_ARCH_WINDOWSCE) +# define Q_BASIC_ATOMIC_INITIALIZER(a) { {(a)} } #else # define Q_BASIC_ATOMIC_INITIALIZER(a) { (a) } #endif |