Ensure that the pointer-sized QAtomicInteger specialization exists

This is already implemented in qatomic_x86.h, qatomic_ia64.h,
qatomic_mips.h, qatomic_armv6.h, and qatomic_cxx11.h. For
qatomic_msvc.h, we've just fixed it.

For qatomic_gcc.h, we know that the compiler supports it, so just add
it. According to the GCC manual, it might print a warning on some
platforms, so we only enable that on 64-bit builds.

For qatomic_unix.h, the support was missing (along with support for
unsigned 32-bit), so this commits adds it.

For qatomic_armv5.h, the platform does not always support 64-bit
atomics, but ARMv5 cannot compile in 64-bit mode anyway.

Change-Id: Ia8b3b5c641f11e5df05937fe7442be0a223174ef
Reviewed-by: Lars Knoll <lars.knoll@digia.com>
This commit is contained in:
Thiago Macieira 2013-12-02 19:22:57 -08:00 committed by The Qt Project
parent e4533e3aeb
commit 8d2a9bcf1d
4 changed files with 78 additions and 1 deletions

View File

@ -75,6 +75,16 @@ template<> struct QAtomicIntegerTraits<char32_t> { enum { IsInteger = 1 }; };
#define Q_ATOMIC_POINTER_FETCH_AND_STORE_IS_SOMETIMES_NATIVE
#define Q_ATOMIC_POINTER_FETCH_AND_ADD_IS_SOMETIMES_NATIVE
#if QT_POINTER_SIZE == 8
# define Q_ATOMIC_INT64_IS_SUPPORTED
# define Q_ATOMIC_INT64_REFERENCE_COUNTING_IS_SOMETIMES_NATIVE
# define Q_ATOMIC_INT64_TEST_AND_SET_IS_SOMETIMES_NATIVE
# define Q_ATOMIC_INT64_FETCH_AND_STORE_IS_SOMETIMES_NATIVE
# define Q_ATOMIC_INT64_FETCH_AND_ADD_IS_SOMETIMES_NATIVE
template<> struct QAtomicIntegerTraits<long long> { enum { IsInteger = 1 }; };
template<> struct QAtomicIntegerTraits<unsigned long long> { enum { IsInteger = 1 }; };
#endif
template <typename X> struct QAtomicOps: QGenericAtomicOps<QAtomicOps<X> >
{
// The GCC intrinsics all have fully-ordered memory semantics, so we define

View File

@ -64,6 +64,19 @@ bool QAtomicOps<int>::testAndSetRelaxed(int &_q_value, int expectedValue, int ne
return returnValue;
}
Q_CORE_EXPORT
bool QAtomicOps<long long>::testAndSetRelaxed(Type &_q_value, Type expectedValue, Type newValue) Q_DECL_NOTHROW
{
bool returnValue = false;
pthread_mutex_lock(&qAtomicMutex);
if (_q_value == expectedValue) {
_q_value = newValue;
returnValue = true;
}
pthread_mutex_unlock(&qAtomicMutex);
return returnValue;
}
Q_CORE_EXPORT
bool QAtomicOps<void *>::testAndSetRelaxed(void *&_q_value, void *expectedValue, void *newValue) Q_DECL_NOTHROW
{

View File

@ -64,15 +64,25 @@ QT_END_NAMESPACE
#define Q_ATOMIC_INT32_FETCH_AND_STORE_IS_NOT_NATIVE
#define Q_ATOMIC_INT32_FETCH_AND_ADD_IS_NOT_NATIVE
#define Q_ATOMIC_INT64_IS_SUPPORTED
#define Q_ATOMIC_INT64_REFERENCE_COUNTING_IS_NOT_NATIVE
#define Q_ATOMIC_INT64_TEST_AND_SET_IS_NOT_NATIVE
#define Q_ATOMIC_INT64_FETCH_AND_STORE_IS_NOT_NATIVE
#define Q_ATOMIC_INT64_FETCH_AND_ADD_IS_NOT_NATIVE
#define Q_ATOMIC_POINTER_TEST_AND_SET_IS_NOT_NATIVE
#define Q_ATOMIC_POINTER_FETCH_AND_STORE_IS_NOT_NATIVE
#define Q_ATOMIC_POINTER_FETCH_AND_ADD_IS_NOT_NATIVE
template<> struct QAtomicIntegerTraits<int> { enum { IsInteger = 1 }; };
template<> struct QAtomicIntegerTraits<unsigned> { enum { IsInteger = 1 }; };
template<> struct QAtomicIntegerTraits<long long> { enum { IsInteger = 1 }; };
template<> struct QAtomicIntegerTraits<unsigned long long> { enum { IsInteger = 1 }; };
// No definition, needs specialization
template <typename T> struct QAtomicOps;
// 32-bit version
template <>
struct QAtomicOps<int> : QGenericAtomicOps<QAtomicOps<int> >
{
@ -83,6 +93,18 @@ struct QAtomicOps<int> : QGenericAtomicOps<QAtomicOps<int> >
Q_CORE_EXPORT static bool testAndSetRelaxed(int &_q_value, int expectedValue, int newValue) Q_DECL_NOTHROW;
};
// 64-bit version
template <>
struct QAtomicOps<long long> : QGenericAtomicOps<QAtomicOps<long long> >
{
typedef long long Type;
static inline Q_DECL_CONSTEXPR bool isTestAndSetNative() Q_DECL_NOTHROW { return false; }
static inline Q_DECL_CONSTEXPR bool isTestAndSetWaitFree() Q_DECL_NOTHROW { return false; }
Q_CORE_EXPORT static bool testAndSetRelaxed(Type &_q_value, Type expectedValue, Type newValue) Q_DECL_NOTHROW;
};
// pointer version
template <>
struct QAtomicOps<void *> : QGenericAtomicOps<QAtomicOps<void *> >
{
@ -113,5 +135,23 @@ struct QAtomicOps<T *> : QGenericAtomicOps<QAtomicOps<T *> >
}
};
// 32- and 64-bit unsigned versions
template <> struct QAtomicOps<unsigned> : QAtomicOps<int>
{
typedef unsigned Type;
Q_CORE_EXPORT static bool testAndSetRelaxed(Type &_q_value, Type expectedValue, Type newValue) Q_DECL_NOTHROW
{
return QAtomicOps<int>::testAndSetRelaxed(reinterpret_cast<int &>(_q_value), int(expectedValue), int(newValue));
}
};
template <> struct QAtomicOps<unsigned long long> : QAtomicOps<long long>
{
typedef unsigned long longType;
Q_CORE_EXPORT static bool testAndSetRelaxed(Type &_q_value, Type expectedValue, Type newValue) Q_DECL_NOTHROW
{
return QAtomicOps<long long>::testAndSetRelaxed(reinterpret_cast<long long &>(_q_value), int(expectedValue), int(newValue));
}
};
QT_END_NAMESPACE
#endif // QATOMIC_UNIX_H

View File

@ -72,9 +72,10 @@
\li 32-bit: int, unsigned int, qint32, quint32, char32_t (C++11)
\li 64-bit: long long, unsigned long long, qint64, quint64
\li platform-specific size: long, unsigned long
\li pointer size: qintptr, quintptr, qptrdiff
\endlist
Of the list above, only the 32-bit-sized instantiations are guaranteed to
Of the list above, only the 32-bit- and pointer-sized instantiations are guaranteed to
work on all platforms. Support for other sizes depends on the compiler and
processor architecture the code is being compiled for. To test whether the
other types are supported, check the macro \c Q_ATOMIC_INT\e{nn}_IS_SUPPORTED,
@ -1213,3 +1214,16 @@
#ifndef Q_ATOMIC_INT32_IS_SUPPORTED
# error "Q_ATOMIC_INT32_IS_SUPPORTED must be defined"
#endif
#if !defined(Q_ATOMIC_INT64_IS_SUPPORTED) && QT_POINTER_SIZE == 8
// 64-bit platform
# error "Q_ATOMIC_INT64_IS_SUPPORTED must be defined on a 64-bit platform"
#endif
QT_BEGIN_NAMESPACE
// The following three specializations must always be defined
Q_STATIC_ASSERT(sizeof(QAtomicInteger<unsigned>));
Q_STATIC_ASSERT(sizeof(QAtomicInteger<quintptr>));
Q_STATIC_ASSERT(sizeof(QAtomicInteger<qptrdiff>));
QT_END_NAMESPACE