diff options
31 files changed, 533 insertions, 83 deletions
diff --git a/src/corelib/arch/qatomic_armv6.h b/src/corelib/arch/qatomic_armv6.h index b8401d185d..37df64141c 100644 --- a/src/corelib/arch/qatomic_armv6.h +++ b/src/corelib/arch/qatomic_armv6.h @@ -210,17 +210,9 @@ T QBasicAtomicOps<4>::fetchAndAddRelaxed(T &_q_value, typename QAtomicAdditiveTy || defined(__ARM_ARCH_6K__) // LDREXB, LDREXH and LDREXD are available on ARMv6K or higher -template<> struct QAtomicIntegerTraits<char> { enum { IsInteger = 1 }; }; -template<> struct QAtomicIntegerTraits<signed char> { enum { IsInteger = 1 }; }; -template<> struct QAtomicIntegerTraits<unsigned char> { enum { IsInteger = 1 }; }; -template<> struct QAtomicIntegerTraits<short> { enum { IsInteger = 1 }; }; -template<> struct QAtomicIntegerTraits<unsigned short> { enum { IsInteger = 1 }; }; -template<> struct QAtomicIntegerTraits<long long> { enum { IsInteger = 1 }; }; -template<> struct QAtomicIntegerTraits<unsigned long long> { enum { IsInteger = 1 }; }; - -# ifdef Q_COMPILER_UNICODE_STRINGS -template<> struct QAtomicIntegerTraits<char16_t> { enum { IsInteger = 1 }; }; -# endif +template<> struct QAtomicOpsSupport<1> { enum { IsSupported = 1 }; }; +template<> struct QAtomicOpsSupport<2> { enum { IsSupported = 1 }; }; +template<> struct QAtomicOpsSupport<8> { enum { IsSupported = 1 }; }; #define Q_ATOMIC_INT8_IS_SUPPORTED #define Q_ATOMIC_INT8_REFERENCE_COUNTING_IS_ALWAYS_NATIVE diff --git a/src/corelib/arch/qatomic_cxx11.h b/src/corelib/arch/qatomic_cxx11.h index 87eb7b3fab..85575da20e 100644 --- a/src/corelib/arch/qatomic_cxx11.h +++ b/src/corelib/arch/qatomic_cxx11.h @@ -70,17 +70,9 @@ QT_END_NAMESPACE #define Q_ATOMIC_POINTER_FETCH_AND_STORE_IS_SOMETIMES_NATIVE #define Q_ATOMIC_POINTER_FETCH_AND_ADD_IS_SOMETIMES_NATIVE -template<> struct QAtomicIntegerTraits<char> { enum { IsInteger = 1 }; }; -template<> struct QAtomicIntegerTraits<signed char> { enum { IsInteger = 1 }; }; -template<> struct QAtomicIntegerTraits<unsigned char> { enum { IsInteger = 1 }; }; -template<> struct QAtomicIntegerTraits<short> { enum { IsInteger = 1 }; }; -template<> struct QAtomicIntegerTraits<unsigned short> { enum { IsInteger = 1 }; }; -template<> struct QAtomicIntegerTraits<long long> { enum { IsInteger = 1 }; }; -template<> struct QAtomicIntegerTraits<unsigned long long> { enum { IsInteger = 1 }; }; - -# ifdef Q_COMPILER_UNICODE_STRINGS -template<> struct QAtomicIntegerTraits<char16_t> { enum { IsInteger = 1 }; }; -# endif +template<> struct QAtomicOpsSupport<1> { enum { IsSupported = 1 }; }; +template<> struct QAtomicOpsSupport<2> { enum { IsSupported = 1 }; }; +template<> struct QAtomicOpsSupport<8> { enum { IsSupported = 1 }; }; #define Q_ATOMIC_INT8_IS_SUPPORTED #define Q_ATOMIC_INT8_REFERENCE_COUNTING_IS_ALWAYS_NATIVE diff --git a/src/corelib/arch/qatomic_gcc.h b/src/corelib/arch/qatomic_gcc.h index 7a8672510f..052453c082 100644 --- a/src/corelib/arch/qatomic_gcc.h +++ b/src/corelib/arch/qatomic_gcc.h @@ -75,8 +75,7 @@ QT_END_NAMESPACE # 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 }; }; +template<> struct QAtomicOpsSupport<8> { enum { IsSupported = 1 }; }; #endif template <typename X> struct QAtomicOps: QGenericAtomicOps<QAtomicOps<X> > diff --git a/src/corelib/arch/qatomic_ia64.h b/src/corelib/arch/qatomic_ia64.h index 2abba95c6c..0075f32a42 100644 --- a/src/corelib/arch/qatomic_ia64.h +++ b/src/corelib/arch/qatomic_ia64.h @@ -123,17 +123,9 @@ QT_END_NAMESPACE #define Q_ATOMIC_INT64_FETCH_AND_ADD_IS_ALWAYS_NATIVE -template<> struct QAtomicIntegerTraits<char> { enum { IsInteger = 1 }; }; -template<> struct QAtomicIntegerTraits<signed char> { enum { IsInteger = 1 }; }; -template<> struct QAtomicIntegerTraits<unsigned char> { enum { IsInteger = 1 }; }; -template<> struct QAtomicIntegerTraits<short> { enum { IsInteger = 1 }; }; -template<> struct QAtomicIntegerTraits<unsigned short> { enum { IsInteger = 1 }; }; -template<> struct QAtomicIntegerTraits<long long> { enum { IsInteger = 1 }; }; -template<> struct QAtomicIntegerTraits<unsigned long long> { enum { IsInteger = 1 }; }; - -# ifdef Q_COMPILER_UNICODE_STRINGS -template<> struct QAtomicIntegerTraits<char16_t> { enum { IsInteger = 1 }; }; -# endif +template<> struct QAtomicOpsSupport<1> { enum { IsSupported = 1 }; }; +template<> struct QAtomicOpsSupport<2> { enum { IsSupported = 1 }; }; +template<> struct QAtomicOpsSupport<8> { enum { IsSupported = 1 }; }; template <int size> struct QBasicAtomicOps: QGenericAtomicOps<QBasicAtomicOps<size> > { diff --git a/src/corelib/arch/qatomic_mips.h b/src/corelib/arch/qatomic_mips.h index e9a4e31c75..9c744b885d 100644 --- a/src/corelib/arch/qatomic_mips.h +++ b/src/corelib/arch/qatomic_mips.h @@ -232,14 +232,7 @@ T QBasicAtomicOps<4>::fetchAndAddRelaxed(T &_q_value, typename QAtomicAdditiveTy #define Q_ATOMIC_INT64_FETCH_AND_STORE_IS_ALWAYS_NATIVE #define Q_ATOMIC_INT64_FETCH_AND_ADD_IS_ALWAYS_NATIVE -template<> struct QAtomicIntegerTraits<long long> { enum { IsInteger = 1 }; }; -template<> struct QAtomicIntegerTraits<unsigned long long > { enum { IsInteger = 1 }; }; - -#ifdef Q_COMPILER_UNICODE_STRINGS -template<> struct QAtomicIntegerTraits<char16_t> -{ enum { IsInteger = sizeof(char16_t) == sizeof(int) ? 1 : -1 }; }; -template<> struct QAtomicIntegerTraits<char32_t> { enum { IsInteger = 1 }; }; -#endif +template<> struct QAtomicOpsSupport<8> { enum { IsSupported = 1 }; }; template<> template<typename T> inline bool QBasicAtomicOps<8>::ref(T &_q_value) Q_DECL_NOTHROW diff --git a/src/corelib/arch/qatomic_msvc.h b/src/corelib/arch/qatomic_msvc.h index 7ba70259e9..1cbb1442ed 100644 --- a/src/corelib/arch/qatomic_msvc.h +++ b/src/corelib/arch/qatomic_msvc.h @@ -275,8 +275,7 @@ QT_END_NAMESPACE # define Q_ATOMIC_INT16_FETCH_AND_ADD_IS_ALWAYS_NATIVE # define Q_ATOMIC_INT16_FETCH_AND_ADD_IS_WAIT_FREE -template<> struct QAtomicIntegerTraits<short> { enum { IsInteger = 1 }; }; -template<> struct QAtomicIntegerTraits<unsigned short> { enum { IsInteger = 1 }; }; +template<> struct QAtomicOpsSupport<2> { enum { IsSupported = 1 }; }; #endif #ifdef Q_ATOMIC_INT64_IS_SUPPORTED @@ -292,8 +291,7 @@ template<> struct QAtomicIntegerTraits<unsigned short> { enum { IsInteger = 1 }; # define Q_ATOMIC_INT64_FETCH_AND_ADD_IS_ALWAYS_NATIVE # define Q_ATOMIC_INT64_FETCH_AND_ADD_IS_WAIT_FREE -template<> struct QAtomicIntegerTraits<long long> { enum { IsInteger = 1 }; }; -template<> struct QAtomicIntegerTraits<unsigned long long> { enum { IsInteger = 1 }; }; +template<> struct QAtomicOpsSupport<8> { enum { IsSupported = 1 }; }; #endif //////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/src/corelib/arch/qatomic_unix.h b/src/corelib/arch/qatomic_unix.h index 493927fac0..6ed9864073 100644 --- a/src/corelib/arch/qatomic_unix.h +++ b/src/corelib/arch/qatomic_unix.h @@ -74,9 +74,6 @@ QT_END_NAMESPACE #define Q_ATOMIC_POINTER_FETCH_AND_STORE_IS_NOT_NATIVE #define Q_ATOMIC_POINTER_FETCH_AND_ADD_IS_NOT_NATIVE -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; diff --git a/src/corelib/arch/qatomic_x86.h b/src/corelib/arch/qatomic_x86.h index 6ed283396d..2013d8f991 100644 --- a/src/corelib/arch/qatomic_x86.h +++ b/src/corelib/arch/qatomic_x86.h @@ -117,18 +117,9 @@ template <typename T> struct QAtomicOps : QBasicAtomicOps<sizeof(T)> #if defined(Q_CC_GNU) -template<> struct QAtomicIntegerTraits<char> { enum { IsInteger = 1 }; }; -template<> struct QAtomicIntegerTraits<signed char> { enum { IsInteger = 1 }; }; -template<> struct QAtomicIntegerTraits<unsigned char> { enum { IsInteger = 1 }; }; -template<> struct QAtomicIntegerTraits<short> { enum { IsInteger = 1 }; }; -template<> struct QAtomicIntegerTraits<unsigned short> { enum { IsInteger = 1 }; }; -template<> struct QAtomicIntegerTraits<long long> { enum { IsInteger = 1 }; }; -template<> struct QAtomicIntegerTraits<unsigned long long> { enum { IsInteger = 1 }; }; - -# ifdef Q_COMPILER_UNICODE_STRINGS -template<> struct QAtomicIntegerTraits<char16_t> { enum { IsInteger = 1 }; }; -# endif - +template<> struct QAtomicOpsSupport<1> { enum { IsSupported = 1 }; }; +template<> struct QAtomicOpsSupport<2> { enum { IsSupported = 1 }; }; +template<> struct QAtomicOpsSupport<8> { enum { IsSupported = 1 }; }; /* * Guide for the inline assembly below: diff --git a/src/corelib/thread/qbasicatomic.h b/src/corelib/thread/qbasicatomic.h index 9fa12ba811..f75a24ae10 100644 --- a/src/corelib/thread/qbasicatomic.h +++ b/src/corelib/thread/qbasicatomic.h @@ -114,7 +114,8 @@ class QBasicAtomicInteger public: typedef QAtomicOps<T> Ops; // static check that this is a valid integer - Q_STATIC_ASSERT_X(QAtomicIntegerTraits<T>::IsInteger, "Template parameter is not a supported integer on this platform"); + Q_STATIC_ASSERT_X(QTypeInfo<T>::isIntegral, "template parameter is not an integral type"); + Q_STATIC_ASSERT_X(QAtomicOpsSupport<sizeof(T)>::IsSupported, "template parameter is an integral of a size not supported on this platform"); typename Ops::Type _q_value; diff --git a/src/corelib/thread/qgenericatomic.h b/src/corelib/thread/qgenericatomic.h index bbdc57ca50..eacde411b9 100644 --- a/src/corelib/thread/qgenericatomic.h +++ b/src/corelib/thread/qgenericatomic.h @@ -60,20 +60,8 @@ QT_END_NAMESPACE #define always_inline #endif -template<typename T> struct QAtomicIntegerTraits { enum { IsInteger = 0 }; }; - -// these integers are always supported, on all platforms -// - int, unsigned int and char32_t are 32-bit wide -// - long and unsigned long might be 64-bit wide on 64-bit platforms, -// but 64-bit integer support is required anyway -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 }; }; -#ifdef Q_COMPILER_UNICODE_STRINGS -template<> struct QAtomicIntegerTraits<char32_t> -{ enum { IsInteger = sizeof(char32_t) == sizeof(int) ? 1 : -1 }; }; -#endif +template<int> struct QAtomicOpsSupport { enum { IsSupported = 0 }; }; +template<> struct QAtomicOpsSupport<4> { enum { IsSupported = 1 }; }; template <typename T> struct QAtomicAdditiveType { diff --git a/tests/auto/corelib/thread/qatomicint/tst_qatomicint.cpp b/tests/auto/corelib/thread/qatomicint/tst_qatomicint.cpp index fefc126bba..42b3a52531 100644 --- a/tests/auto/corelib/thread/qatomicint/tst_qatomicint.cpp +++ b/tests/auto/corelib/thread/qatomicint/tst_qatomicint.cpp @@ -99,10 +99,6 @@ static inline void assemblyMarker(void *ptr = 0) puts((char *)ptr + I); } -QT_BEGIN_NAMESPACE -template <typename T> class QBasicAtomicInteger; // even if it this class isn't supported -QT_END_NAMESPACE - template <typename T, typename Atomic> static void warningFreeHelperTemplate() { @@ -185,7 +181,7 @@ void tst_QAtomicInt::warningFreeHelper() qFatal("This code is bogus, and shouldn't be run. We're looking for compiler warnings only."); warningFreeHelperTemplate<int, QBasicAtomicInt>(); -#ifdef Q_ATOMIC_INT32_IS_SUPPORTED + // 32-bit are always supported: warningFreeHelperTemplate<int, QBasicAtomicInteger<int> >(); warningFreeHelperTemplate<unsigned int, QBasicAtomicInteger<unsigned int> >(); constexprFunctionsHelperTemplate<QBasicAtomicInteger<int> >(); @@ -194,7 +190,18 @@ void tst_QAtomicInt::warningFreeHelper() warningFreeHelperTemplate<qint16, QBasicAtomicInteger<char32_t> >(); constexprFunctionsHelperTemplate<QBasicAtomicInteger<char32_t> >(); # endif -#endif + + // pointer-sized integers are always supported: + warningFreeHelperTemplate<int, QBasicAtomicInteger<qptrdiff> >(); + warningFreeHelperTemplate<unsigned int, QBasicAtomicInteger<quintptr> >(); + constexprFunctionsHelperTemplate<QBasicAtomicInteger<qptrdiff> >(); + constexprFunctionsHelperTemplate<QBasicAtomicInteger<quintptr> >(); + + // long is always supported because it's either 32-bit or pointer-sized: + warningFreeHelperTemplate<int, QBasicAtomicInteger<long int> >(); + warningFreeHelperTemplate<unsigned int, QBasicAtomicInteger<unsigned long int> >(); + constexprFunctionsHelperTemplate<QBasicAtomicInteger<long int> >(); + constexprFunctionsHelperTemplate<QBasicAtomicInteger<unsigned long int> >(); #ifdef Q_ATOMIC_INT16_IS_SUPPORTED warningFreeHelperTemplate<qint16, QBasicAtomicInteger<qint16> >(); diff --git a/tests/auto/corelib/thread/qatomicinteger/char/char.pro b/tests/auto/corelib/thread/qatomicinteger/char/char.pro new file mode 100644 index 0000000000..51ef1add8f --- /dev/null +++ b/tests/auto/corelib/thread/qatomicinteger/char/char.pro @@ -0,0 +1,2 @@ +TYPE = $$basename(PWD) +include(../qatomicinteger.pri) diff --git a/tests/auto/corelib/thread/qatomicinteger/char16_t/char16_t.pro b/tests/auto/corelib/thread/qatomicinteger/char16_t/char16_t.pro new file mode 100644 index 0000000000..51ef1add8f --- /dev/null +++ b/tests/auto/corelib/thread/qatomicinteger/char16_t/char16_t.pro @@ -0,0 +1,2 @@ +TYPE = $$basename(PWD) +include(../qatomicinteger.pri) diff --git a/tests/auto/corelib/thread/qatomicinteger/char32_t/char32_t.pro b/tests/auto/corelib/thread/qatomicinteger/char32_t/char32_t.pro new file mode 100644 index 0000000000..51ef1add8f --- /dev/null +++ b/tests/auto/corelib/thread/qatomicinteger/char32_t/char32_t.pro @@ -0,0 +1,2 @@ +TYPE = $$basename(PWD) +include(../qatomicinteger.pri) diff --git a/tests/auto/corelib/thread/qatomicinteger/int/int.pro b/tests/auto/corelib/thread/qatomicinteger/int/int.pro new file mode 100644 index 0000000000..51ef1add8f --- /dev/null +++ b/tests/auto/corelib/thread/qatomicinteger/int/int.pro @@ -0,0 +1,2 @@ +TYPE = $$basename(PWD) +include(../qatomicinteger.pri) diff --git a/tests/auto/corelib/thread/qatomicinteger/long/long.pro b/tests/auto/corelib/thread/qatomicinteger/long/long.pro new file mode 100644 index 0000000000..51ef1add8f --- /dev/null +++ b/tests/auto/corelib/thread/qatomicinteger/long/long.pro @@ -0,0 +1,2 @@ +TYPE = $$basename(PWD) +include(../qatomicinteger.pri) diff --git a/tests/auto/corelib/thread/qatomicinteger/qatomicinteger.pri b/tests/auto/corelib/thread/qatomicinteger/qatomicinteger.pri new file mode 100644 index 0000000000..dc7cc8bcec --- /dev/null +++ b/tests/auto/corelib/thread/qatomicinteger/qatomicinteger.pri @@ -0,0 +1,7 @@ +isEmpty(TYPE): error("Project must define TYPE variable") + +CONFIG += testcase parallel_test +QT = core testlib +TARGET = tst_qatomicinteger_$$TYPE +SOURCES = $$PWD/tst_qatomicinteger.cpp +DEFINES += QATOMIC_TEST_TYPE=$$TYPE tst_QAtomicIntegerXX=tst_QAtomicInteger_$$TYPE diff --git a/tests/auto/corelib/thread/qatomicinteger/qatomicinteger.pro b/tests/auto/corelib/thread/qatomicinteger/qatomicinteger.pro new file mode 100644 index 0000000000..373e8801a4 --- /dev/null +++ b/tests/auto/corelib/thread/qatomicinteger/qatomicinteger.pro @@ -0,0 +1,19 @@ +TEMPLATE=subdirs +SUBDIRS=\ + char \ + char16_t \ + char32_t \ + int \ + long \ + qlonglong \ + qptrdiff \ + quintptr \ + qulonglong \ + schar \ + short \ + uchar \ + uint \ + ulong \ + ushort \ + wchar_t \ + diff --git a/tests/auto/corelib/thread/qatomicinteger/qlonglong/qlonglong.pro b/tests/auto/corelib/thread/qatomicinteger/qlonglong/qlonglong.pro new file mode 100644 index 0000000000..51ef1add8f --- /dev/null +++ b/tests/auto/corelib/thread/qatomicinteger/qlonglong/qlonglong.pro @@ -0,0 +1,2 @@ +TYPE = $$basename(PWD) +include(../qatomicinteger.pri) diff --git a/tests/auto/corelib/thread/qatomicinteger/qptrdiff/qptrdiff.pro b/tests/auto/corelib/thread/qatomicinteger/qptrdiff/qptrdiff.pro new file mode 100644 index 0000000000..51ef1add8f --- /dev/null +++ b/tests/auto/corelib/thread/qatomicinteger/qptrdiff/qptrdiff.pro @@ -0,0 +1,2 @@ +TYPE = $$basename(PWD) +include(../qatomicinteger.pri) diff --git a/tests/auto/corelib/thread/qatomicinteger/quintptr/quintptr.pro b/tests/auto/corelib/thread/qatomicinteger/quintptr/quintptr.pro new file mode 100644 index 0000000000..51ef1add8f --- /dev/null +++ b/tests/auto/corelib/thread/qatomicinteger/quintptr/quintptr.pro @@ -0,0 +1,2 @@ +TYPE = $$basename(PWD) +include(../qatomicinteger.pri) diff --git a/tests/auto/corelib/thread/qatomicinteger/qulonglong/qulonglong.pro b/tests/auto/corelib/thread/qatomicinteger/qulonglong/qulonglong.pro new file mode 100644 index 0000000000..51ef1add8f --- /dev/null +++ b/tests/auto/corelib/thread/qatomicinteger/qulonglong/qulonglong.pro @@ -0,0 +1,2 @@ +TYPE = $$basename(PWD) +include(../qatomicinteger.pri) diff --git a/tests/auto/corelib/thread/qatomicinteger/schar/schar.pro b/tests/auto/corelib/thread/qatomicinteger/schar/schar.pro new file mode 100644 index 0000000000..51ef1add8f --- /dev/null +++ b/tests/auto/corelib/thread/qatomicinteger/schar/schar.pro @@ -0,0 +1,2 @@ +TYPE = $$basename(PWD) +include(../qatomicinteger.pri) diff --git a/tests/auto/corelib/thread/qatomicinteger/short/short.pro b/tests/auto/corelib/thread/qatomicinteger/short/short.pro new file mode 100644 index 0000000000..51ef1add8f --- /dev/null +++ b/tests/auto/corelib/thread/qatomicinteger/short/short.pro @@ -0,0 +1,2 @@ +TYPE = $$basename(PWD) +include(../qatomicinteger.pri) diff --git a/tests/auto/corelib/thread/qatomicinteger/tst_qatomicinteger.cpp b/tests/auto/corelib/thread/qatomicinteger/tst_qatomicinteger.cpp new file mode 100644 index 0000000000..a7139b6a9a --- /dev/null +++ b/tests/auto/corelib/thread/qatomicinteger/tst_qatomicinteger.cpp @@ -0,0 +1,441 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Intel Corporation +** Contact: http://www.qt-project.org/legal +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QtTest> +#include <QAtomicInt> + +#include <limits> +#include <limits.h> +#include <wchar.h> + +#if !defined(Q_ATOMIC_INT32_IS_SUPPORTED) +# error "QAtomicInteger for 32-bit types must be supported!" +#endif +#if QT_POINTER_SIZE == 8 && !defined(Q_ATOMIC_INT64_IS_SUPPORTED) +# error "QAtomicInteger for 64-bit types must be supported on 64-bit builds!" +#endif + +// always supported types: +#define TYPE_SUPPORTED_int 1 +#define TYPE_SUPPORTED_uint 1 +#define TYPE_SUPPORTED_long 1 +#define TYPE_SUPPORTED_ulong 1 +#define TYPE_SUPPORTED_qptrdiff 1 +#define TYPE_SUPPORTED_quintptr 1 +#if (defined(__SIZEOF_WCHAR_T__) && (__SIZEOF_WCHAR_T__-0) > 2) \ + || (defined(WCHAR_MAX) && (WCHAR_MAX-0 > 0x10000)) +# define TYPE_SUPPORTED_wchar_t 1 +#endif +#ifdef Q_COMPILER_UNICODE_STRINGS +# define TYPE_SUPPORTED_char32_t 1 +#endif + +#ifdef Q_ATOMIC_INT8_IS_SUPPORTED +# define TYPE_SUPPORTED_char 1 +# define TYPE_SUPPORTED_uchar 1 +# define TYPE_SUPPORTED_schar 1 +#endif +#ifdef Q_ATOMIC_INT16_IS_SUPPORTED +# define TYPE_SUPPORTED_short 1 +# define TYPE_SUPPORTED_ushort 1 +# ifdef Q_COMPILER_UNICODE_STRINGS +# define TYPE_SUPPORTED_char16_t 1 +# endif +# ifndef TYPE_SUPPORTED_wchar_t +# define TYPE_SUPPORTED_wchar_t 1 +# endif +#endif +#ifdef Q_ATOMIC_INT64_IS_SUPPORTED +# define TYPE_SUPPORTED_qlonglong 1 +# define TYPE_SUPPORTED_qulonglong 1 +#endif + +#ifdef Q_MOC_RUN +# define QATOMIC_TYPE_SUPPORTED(type) 1 +#else +# define QATOMIC_TYPE_SUPPORTED2(type) TYPE_SUPPORTED_ ## type +# define QATOMIC_TYPE_SUPPORTED(type) QATOMIC_TYPE_SUPPORTED2(type) +#endif // Q_MOC_RUN + +#if QATOMIC_TYPE_SUPPORTED(QATOMIC_TEST_TYPE) +# define TEST_TYPE QATOMIC_TEST_TYPE +#else +# define TEST_TYPE int +# define QATOMIC_TEST_NOT_SUPPORTED +#endif + +#if defined(Q_CC_GNU) && !defined(Q_CC_INTEL) +# pragma GCC diagnostic ignored "-Wtype-limits" +# pragma GCC diagnostic ignored "-Wsign-compare" +#endif +#if defined(Q_CC_CLANG) && !defined(Q_CC_INTEL) +# pragma clang diagnostic ignored "-Wtautological-constant-out-of-range-compare" +#endif + +typedef signed char schar; + +typedef TEST_TYPE Type; +typedef Type T; // shorthand +enum { + TypeIsUnsigned = Type(-1) > Type(0), + TypeIsSigned = !TypeIsUnsigned +}; + +template <bool> struct LargeIntTemplate; +template <> struct LargeIntTemplate<true> { typedef quint64 Type; }; +template <> struct LargeIntTemplate<false> { typedef qint64 Type; }; +typedef LargeIntTemplate<TypeIsUnsigned>::Type LargeInt; + +class tst_QAtomicIntegerXX : public QObject +{ + Q_OBJECT + + void addData(); + +private Q_SLOTS: + void initTestCase(); + void static_checks(); + + void constructor_data() { addData(); } + void constructor(); + + void copy_data() { addData(); } + void copy(); + + void assign_data() { addData(); } + void assign(); + + void loadAcquireStoreRelease_data() { addData(); } + void loadAcquireStoreRelease(); + + void refDeref_data() { addData(); } + void refDeref(); + + void testAndSet_data() { addData(); } + void testAndSet(); + + void fetchAndStore_data() { addData(); } + void fetchAndStore(); + + void fetchAndAdd_data() { addData(); } + void fetchAndAdd(); +}; + +template <bool> inline void booleanHelper() { } +template <typename T> struct TypeInStruct { T type; }; + +void tst_QAtomicIntegerXX::static_checks() +{ + Q_STATIC_ASSERT(sizeof(QAtomicInteger<T>) == sizeof(T)); + Q_STATIC_ASSERT(Q_ALIGNOF(QAtomicInteger<T>) == Q_ALIGNOF(TypeInStruct<T>)); + + // statements with no effect + (void) QAtomicInteger<T>::isReferenceCountingNative(); + (void) QAtomicInteger<T>::isReferenceCountingWaitFree(); + (void) QAtomicInteger<T>::isTestAndSetNative(); + (void) QAtomicInteger<T>::isTestAndSetWaitFree(); + (void) QAtomicInteger<T>::isFetchAndStoreNative(); + (void) QAtomicInteger<T>::isFetchAndStoreWaitFree(); + (void) QAtomicInteger<T>::isFetchAndAddNative(); + (void) QAtomicInteger<T>::isFetchAndAddWaitFree(); + +#ifdef Q_COMPILER_CONSTEXPR + // this is a compile-time test only + booleanHelper<QAtomicInteger<T>::isReferenceCountingNative()>(); + booleanHelper<QAtomicInteger<T>::isReferenceCountingWaitFree()>(); + booleanHelper<QAtomicInteger<T>::isTestAndSetNative()>(); + booleanHelper<QAtomicInteger<T>::isTestAndSetWaitFree()>(); + booleanHelper<QAtomicInteger<T>::isFetchAndStoreNative()>(); + booleanHelper<QAtomicInteger<T>::isFetchAndStoreWaitFree()>(); + booleanHelper<QAtomicInteger<T>::isFetchAndAddNative()>(); + booleanHelper<QAtomicInteger<T>::isFetchAndAddWaitFree()>(); +#endif +} + +void tst_QAtomicIntegerXX::addData() +{ + typedef std::numeric_limits<T> Limits; + QTest::addColumn<LargeInt>("value"); + QTest::newRow("0") << LargeInt(0); + QTest::newRow("+1") << LargeInt(1); + QTest::newRow("42") << LargeInt(42); + if (TypeIsSigned) { + QTest::newRow("-1") << qint64(-1); + QTest::newRow("-47") << qint64(-47); + } + + // exercise bits + if (TypeIsSigned && Limits::min() < qint64(SCHAR_MIN)) + QTest::newRow("int8_min") << qint64(SCHAR_MIN); + if (Limits::max() > LargeInt(SCHAR_MAX)) + QTest::newRow("int8_max") << LargeInt(SCHAR_MAX); + if (Limits::max() > LargeInt(UCHAR_MAX)) + QTest::newRow("uint8_max") << LargeInt(UCHAR_MAX); + if (TypeIsSigned && Limits::min() < -qint64(UCHAR_MAX)) + QTest::newRow("-uint8_max") << -qint64(UCHAR_MAX); + if (Limits::max() > LargeInt(SHRT_MAX)) + QTest::newRow("int16_max") << LargeInt(SHRT_MAX); + if (TypeIsSigned && Limits::min() < qint64(SHRT_MIN)) + QTest::newRow("int16_min") << qint64(SHRT_MIN); + if (Limits::max() > LargeInt(USHRT_MAX)) + QTest::newRow("uint16_max") << LargeInt(USHRT_MAX); + if (TypeIsSigned && Limits::min() < -qint64(USHRT_MAX)) + QTest::newRow("-uint16_max") << -qint64(USHRT_MAX); + if (Limits::max() > LargeInt(INT_MAX)) + QTest::newRow("int32_max") << LargeInt(INT_MAX); + if (TypeIsSigned && Limits::min() < qint64(INT_MIN)) + QTest::newRow("int32_min") << qint64(INT_MIN); + if (Limits::max() > LargeInt(UINT_MAX)) + QTest::newRow("uint32_max") << LargeInt(UINT_MAX); + if (Limits::max() > LargeInt(std::numeric_limits<qint64>::max())) + QTest::newRow("int64_max") << LargeInt(std::numeric_limits<qint64>::max()); + if (TypeIsSigned && Limits::min() < -qint64(UINT_MAX)) + QTest::newRow("-uint32_max") << -qint64(UINT_MAX); + + if (TypeIsSigned) + QTest::newRow(QT_STRINGIFY(QATOMIC_TEST_TYPE) "_min") << qint64(Limits::min()); + QTest::newRow(QT_STRINGIFY(QATOMIC_TEST_TYPE) "_max") << LargeInt(Limits::max()); +} + +void tst_QAtomicIntegerXX::initTestCase() +{ +#ifdef QATOMIC_TEST_NOT_SUPPORTED + QSKIP("QAtomicInteger<" QT_STRINGIFY(QATOMIC_TEST_TYPE) "> is not supported on this platform"); +#endif +} + +void tst_QAtomicIntegerXX::constructor() +{ + QFETCH(LargeInt, value); + + QAtomicInteger<T> atomic(value); + QCOMPARE(atomic.load(), T(value)); + + QAtomicInteger<T> atomic2 = value; + QCOMPARE(atomic2.load(), T(value)); + + QVERIFY(atomic.load() >= std::numeric_limits<T>::min()); + QVERIFY(atomic.load() <= std::numeric_limits<T>::max()); +} + +void tst_QAtomicIntegerXX::copy() +{ + QFETCH(LargeInt, value); + + QAtomicInteger<T> atomic(value); + QAtomicInteger<T> copy(atomic); + QCOMPARE(copy.load(), atomic.load()); + + QAtomicInteger<T> copy2 = atomic; + QCOMPARE(copy2.load(), atomic.load()); + + // move + QAtomicInteger<T> copy3(qMove(copy)); + QCOMPARE(copy3.load(), atomic.load()); + + QAtomicInteger<T> copy4 = qMove(copy2); + QCOMPARE(copy4.load(), atomic.load()); +} + +void tst_QAtomicIntegerXX::assign() +{ + QFETCH(LargeInt, value); + + QAtomicInteger<T> atomic(value); + QAtomicInteger<T> copy; + copy = atomic; + QCOMPARE(copy.load(), atomic.load()); + + QAtomicInteger<T> copy2; + copy2 = atomic; + QCOMPARE(copy2.load(), atomic.load()); + + // move + QAtomicInteger<T> copy3; + copy3 = qMove(copy); + QCOMPARE(copy3.load(), atomic.load()); + + QAtomicInteger<T> copy4; + copy4 = qMove(copy2); + QCOMPARE(copy4.load(), atomic.load()); +} + +void tst_QAtomicIntegerXX::loadAcquireStoreRelease() +{ + QFETCH(LargeInt, value); + + QAtomicInteger<T> atomic(value); + QCOMPARE(atomic.loadAcquire(), T(value)); + + atomic.storeRelease(~value); + QCOMPARE(atomic.loadAcquire(), T(~value)); + + atomic.storeRelease(value); + QCOMPARE(atomic.load(), T(value)); +} + +void tst_QAtomicIntegerXX::refDeref() +{ + QFETCH(LargeInt, value); + T nextValue = T(value + 1); + T prevValue = T(value - 1); + + QAtomicInteger<T> atomic(value); + QCOMPARE(atomic.ref(), (nextValue != 0)); + QCOMPARE(atomic.load(), nextValue); + QCOMPARE(atomic.deref(), (value != 0)); + QCOMPARE(atomic.load(), T(value)); + QCOMPARE(atomic.deref(), (prevValue != 0)); + QCOMPARE(atomic.load(), prevValue); + QCOMPARE(atomic.ref(), (value != 0)); + QCOMPARE(atomic.load(), T(value)); +} + +void tst_QAtomicIntegerXX::testAndSet() +{ + QFETCH(LargeInt, value); + T newValue = ~T(value); + QAtomicInteger<T> atomic(value); + + QVERIFY(atomic.testAndSetRelaxed(value, newValue)); + QCOMPARE(atomic.load(), newValue); + QVERIFY(!atomic.testAndSetRelaxed(value, newValue)); + QVERIFY(atomic.testAndSetRelaxed(newValue, value)); + QCOMPARE(atomic.load(), T(value)); + + QVERIFY(atomic.testAndSetAcquire(value, newValue)); + QCOMPARE(atomic.load(), newValue); + QVERIFY(!atomic.testAndSetAcquire(value, newValue)); + QVERIFY(atomic.testAndSetAcquire(newValue, value)); + QCOMPARE(atomic.load(), T(value)); + + QVERIFY(atomic.testAndSetRelease(value, newValue)); + QCOMPARE(atomic.loadAcquire(), newValue); + QVERIFY(!atomic.testAndSetRelease(value, newValue)); + QVERIFY(atomic.testAndSetRelease(newValue, value)); + QCOMPARE(atomic.loadAcquire(), T(value)); + + QVERIFY(atomic.testAndSetOrdered(value, newValue)); + QCOMPARE(atomic.loadAcquire(), newValue); + QVERIFY(!atomic.testAndSetOrdered(value, newValue)); + QVERIFY(atomic.testAndSetOrdered(newValue, value)); + QCOMPARE(atomic.loadAcquire(), T(value)); +} + +void tst_QAtomicIntegerXX::fetchAndStore() +{ + QFETCH(LargeInt, value); + T newValue = ~T(value); + QAtomicInteger<T> atomic(value); + + QCOMPARE(atomic.fetchAndStoreRelaxed(newValue), T(value)); + QCOMPARE(atomic.load(), newValue); + QCOMPARE(atomic.fetchAndStoreRelaxed(value), newValue); + QCOMPARE(atomic.load(), T(value)); + + QCOMPARE(atomic.fetchAndStoreAcquire(newValue), T(value)); + QCOMPARE(atomic.load(), newValue); + QCOMPARE(atomic.fetchAndStoreAcquire(value), newValue); + QCOMPARE(atomic.load(), T(value)); + + QCOMPARE(atomic.fetchAndStoreRelease(newValue), T(value)); + QCOMPARE(atomic.loadAcquire(), newValue); + QCOMPARE(atomic.fetchAndStoreRelease(value), newValue); + QCOMPARE(atomic.loadAcquire(), T(value)); + + QCOMPARE(atomic.fetchAndStoreOrdered(newValue), T(value)); + QCOMPARE(atomic.loadAcquire(), newValue); + QCOMPARE(atomic.fetchAndStoreOrdered(value), newValue); + QCOMPARE(atomic.loadAcquire(), T(value)); +} + +void tst_QAtomicIntegerXX::fetchAndAdd() +{ + QFETCH(LargeInt, value); + QAtomicInteger<T> atomic(value); + + // note: this test has undefined behavior for signed max and min + T parcel1 = 42; + T parcel2 = T(0-parcel1); + T newValue1 = T(value) + parcel1; + T newValue2 = T(value) + parcel2; + + QCOMPARE(atomic.fetchAndAddRelaxed(parcel1), T(value)); + QCOMPARE(atomic.load(), newValue1); + QCOMPARE(atomic.fetchAndAddRelaxed(parcel2), newValue1); + QCOMPARE(atomic.load(), T(value)); + QCOMPARE(atomic.fetchAndAddRelaxed(parcel2), T(value)); + QCOMPARE(atomic.load(), newValue2); + QCOMPARE(atomic.fetchAndAddRelaxed(parcel1), newValue2); + QCOMPARE(atomic.load(), T(value)); + + QCOMPARE(atomic.fetchAndAddAcquire(parcel1), T(value)); + QCOMPARE(atomic.load(), newValue1); + QCOMPARE(atomic.fetchAndAddAcquire(parcel2), newValue1); + QCOMPARE(atomic.load(), T(value)); + QCOMPARE(atomic.fetchAndAddAcquire(parcel2), T(value)); + QCOMPARE(atomic.load(), newValue2); + QCOMPARE(atomic.fetchAndAddAcquire(parcel1), newValue2); + QCOMPARE(atomic.load(), T(value)); + + QCOMPARE(atomic.fetchAndAddRelease(parcel1), T(value)); + QCOMPARE(atomic.loadAcquire(), newValue1); + QCOMPARE(atomic.fetchAndAddRelease(parcel2), newValue1); + QCOMPARE(atomic.loadAcquire(), T(value)); + QCOMPARE(atomic.fetchAndAddRelease(parcel2), T(value)); + QCOMPARE(atomic.loadAcquire(), newValue2); + QCOMPARE(atomic.fetchAndAddRelease(parcel1), newValue2); + QCOMPARE(atomic.loadAcquire(), T(value)); + + QCOMPARE(atomic.fetchAndAddOrdered(parcel1), T(value)); + QCOMPARE(atomic.loadAcquire(), newValue1); + QCOMPARE(atomic.fetchAndAddOrdered(parcel2), newValue1); + QCOMPARE(atomic.loadAcquire(), T(value)); + QCOMPARE(atomic.fetchAndAddOrdered(parcel2), T(value)); + QCOMPARE(atomic.loadAcquire(), newValue2); + QCOMPARE(atomic.fetchAndAddOrdered(parcel1), newValue2); + QCOMPARE(atomic.loadAcquire(), T(value)); +} + +#include "tst_qatomicinteger.moc" + +QTEST_APPLESS_MAIN(tst_QAtomicIntegerXX) + diff --git a/tests/auto/corelib/thread/qatomicinteger/uchar/uchar.pro b/tests/auto/corelib/thread/qatomicinteger/uchar/uchar.pro new file mode 100644 index 0000000000..51ef1add8f --- /dev/null +++ b/tests/auto/corelib/thread/qatomicinteger/uchar/uchar.pro @@ -0,0 +1,2 @@ +TYPE = $$basename(PWD) +include(../qatomicinteger.pri) diff --git a/tests/auto/corelib/thread/qatomicinteger/uint/uint.pro b/tests/auto/corelib/thread/qatomicinteger/uint/uint.pro new file mode 100644 index 0000000000..51ef1add8f --- /dev/null +++ b/tests/auto/corelib/thread/qatomicinteger/uint/uint.pro @@ -0,0 +1,2 @@ +TYPE = $$basename(PWD) +include(../qatomicinteger.pri) diff --git a/tests/auto/corelib/thread/qatomicinteger/ulong/ulong.pro b/tests/auto/corelib/thread/qatomicinteger/ulong/ulong.pro new file mode 100644 index 0000000000..51ef1add8f --- /dev/null +++ b/tests/auto/corelib/thread/qatomicinteger/ulong/ulong.pro @@ -0,0 +1,2 @@ +TYPE = $$basename(PWD) +include(../qatomicinteger.pri) diff --git a/tests/auto/corelib/thread/qatomicinteger/ushort/ushort.pro b/tests/auto/corelib/thread/qatomicinteger/ushort/ushort.pro new file mode 100644 index 0000000000..51ef1add8f --- /dev/null +++ b/tests/auto/corelib/thread/qatomicinteger/ushort/ushort.pro @@ -0,0 +1,2 @@ +TYPE = $$basename(PWD) +include(../qatomicinteger.pri) diff --git a/tests/auto/corelib/thread/qatomicinteger/wchar_t/wchar_t.pro b/tests/auto/corelib/thread/qatomicinteger/wchar_t/wchar_t.pro new file mode 100644 index 0000000000..51ef1add8f --- /dev/null +++ b/tests/auto/corelib/thread/qatomicinteger/wchar_t/wchar_t.pro @@ -0,0 +1,2 @@ +TYPE = $$basename(PWD) +include(../qatomicinteger.pri) diff --git a/tests/auto/corelib/thread/thread.pro b/tests/auto/corelib/thread/thread.pro index f529bd8941..f18dad6a4c 100644 --- a/tests/auto/corelib/thread/thread.pro +++ b/tests/auto/corelib/thread/thread.pro @@ -1,6 +1,7 @@ TEMPLATE=subdirs SUBDIRS=\ qatomicint \ + qatomicinteger \ qatomicpointer \ qresultstore \ qfuture \ |