summaryrefslogtreecommitdiffstats
path: root/tests/auto/corelib/thread/qatomicinteger/tst_qatomicinteger.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'tests/auto/corelib/thread/qatomicinteger/tst_qatomicinteger.cpp')
-rw-r--r--tests/auto/corelib/thread/qatomicinteger/tst_qatomicinteger.cpp189
1 files changed, 38 insertions, 151 deletions
diff --git a/tests/auto/corelib/thread/qatomicinteger/tst_qatomicinteger.cpp b/tests/auto/corelib/thread/qatomicinteger/tst_qatomicinteger.cpp
index dce27ee9c1..d1a8a8f729 100644
--- a/tests/auto/corelib/thread/qatomicinteger/tst_qatomicinteger.cpp
+++ b/tests/auto/corelib/thread/qatomicinteger/tst_qatomicinteger.cpp
@@ -1,54 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the test suite of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:GPL-EXCEPT$
-** 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 The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifdef QT_ATOMIC_FORCE_CXX11
-// We need to check if this compiler has C++11 atomics and constexpr support.
-// We can't rely on qcompilerdetection.h because it forces all of qglobal.h to
-// be included, which causes qbasicatomic.h to be included too.
-// Incomplete, but ok
-# if defined(__INTEL_COMPILER) && __INTEL_COMPILER >= 1500 && (__cplusplus >= 201103L || defined(__INTEL_CXX11_MODE__))
-# elif defined(__clang__) && (__cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__))
-# if !__has_feature(cxx_constexpr) || !__has_feature(cxx_atomic) || !__has_include(<atomic>)
-# undef QT_ATOMIC_FORCE_CXX11
-# endif
-# elif defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__) >= 407 && (__cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__))
-# elif defined(_MSC_VER)
- // We need MSVC 2015 because of: atomics (2012), constexpr (2015), and unrestricted unions (2015).
- // Support for constexpr is not working completely on MSVC 2015 but it's enough for the test.
-# else
-# undef QT_ATOMIC_FORCE_CXX11
-# endif
-
-# ifndef QT_ATOMIC_FORCE_CXX11
-# undef QATOMIC_TEST_TYPE
-# define QATOMIC_TEST_TYPE unsupported
-# endif
-#endif
+// Copyright (C) 2016 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QTest>
#include <QAtomicInt>
@@ -57,6 +8,12 @@
#include <limits.h>
#include <wchar.h>
+#if !defined(Q_ATOMIC_INT8_IS_SUPPORTED)
+# error "QAtomicInteger for 8-bit types must be supported!"
+#endif
+#if !defined(Q_ATOMIC_INT16_IS_SUPPORTED)
+# error "QAtomicInteger for 16-bit types must be supported!"
+#endif
#if !defined(Q_ATOMIC_INT32_IS_SUPPORTED)
# error "QAtomicInteger for 32-bit types must be supported!"
#endif
@@ -65,31 +22,21 @@
#endif
// always supported types:
+#define TYPE_SUPPORTED_char 1
+#define TYPE_SUPPORTED_uchar 1
+#define TYPE_SUPPORTED_schar 1
+#define TYPE_SUPPORTED_short 1
+#define TYPE_SUPPORTED_ushort 1
+#define TYPE_SUPPORTED_char16_t 1
+#define TYPE_SUPPORTED_wchar_t 1
#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
-#define TYPE_SUPPORTED_char32_t 1
+#define TYPE_SUPPORTED_char32_t 1
-#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
-# define TYPE_SUPPORTED_char16_t 1
-# 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
@@ -117,6 +64,7 @@ typedef signed char schar;
typedef TEST_TYPE Type;
typedef Type T; // shorthand
+using U = std::make_unsigned_t<T>;
enum {
TypeIsUnsigned = Type(-1) > Type(0),
TypeIsSigned = !TypeIsUnsigned
@@ -127,6 +75,8 @@ template <> struct LargeIntTemplate<true> { typedef quint64 Type; };
template <> struct LargeIntTemplate<false> { typedef qint64 Type; };
typedef LargeIntTemplate<TypeIsUnsigned>::Type LargeInt;
+namespace {
+
class tst_QAtomicIntegerXX : public QObject
{
Q_OBJECT
@@ -342,46 +292,32 @@ void tst_QAtomicIntegerXX::loadAcquireStoreRelease()
void tst_QAtomicIntegerXX::refDeref()
{
QFETCH(LargeInt, value);
- const bool needToPreventOverflow = TypeIsSigned && value == std::numeric_limits<T>::max();
- const bool needToPreventUnderflow = TypeIsSigned && value == std::numeric_limits<T>::min();
- T nextValue = T(value);
- if (!needToPreventOverflow)
- ++nextValue;
- T prevValue = T(value);
- if (!needToPreventUnderflow)
- --prevValue;
+
+ // We perform arithmetic using the unsigned type U to avoid signed
+ // integer overflows in the non-atomic portion (atomics have well-defined,
+ // two's complement overflow, even signed ones).
+ T nextValue = T(U(value) + 1);
+ T prevValue = T(U(value) - 1);
QAtomicInteger<T> atomic(value);
- if (!needToPreventOverflow) {
QCOMPARE(atomic.ref(), (nextValue != 0));
QCOMPARE(atomic.loadRelaxed(), nextValue);
QCOMPARE(atomic.deref(), (value != 0));
- }
QCOMPARE(atomic.loadRelaxed(), T(value));
- if (!needToPreventUnderflow) {
QCOMPARE(atomic.deref(), (prevValue != 0));
QCOMPARE(atomic.loadRelaxed(), prevValue);
QCOMPARE(atomic.ref(), (value != 0));
- }
QCOMPARE(atomic.loadRelaxed(), T(value));
- if (!needToPreventOverflow) {
QCOMPARE(++atomic, nextValue);
QCOMPARE(--atomic, T(value));
- }
- if (!needToPreventUnderflow) {
QCOMPARE(--atomic, prevValue);
QCOMPARE(++atomic, T(value));
- }
- if (!needToPreventOverflow) {
QCOMPARE(atomic++, T(value));
QCOMPARE(atomic--, nextValue);
- }
- if (!needToPreventUnderflow) {
QCOMPARE(atomic--, T(value));
QCOMPARE(atomic++, prevValue);
- }
QCOMPARE(atomic.loadRelaxed(), T(value));
}
@@ -484,80 +420,55 @@ void tst_QAtomicIntegerXX::fetchAndAdd()
QFETCH(LargeInt, value);
QAtomicInteger<T> atomic(value);
+ // We perform the additions using the unsigned type U to avoid signed
+ // integer overflows in the non-atomic portion (atomics have well-defined,
+ // two's complement overflow, even signed ones).
T parcel1 = 42;
T parcel2 = T(0-parcel1);
+ T newValue1 = T(U(value) + parcel1);
+ T newValue2 = T(U(value) + parcel2);
- const bool needToPreventOverflow = TypeIsSigned && value > std::numeric_limits<T>::max() + parcel2;
- const bool needToPreventUnderflow = TypeIsSigned && value < std::numeric_limits<T>::min() + parcel1;
-
- T newValue1 = T(value);
- if (!needToPreventOverflow)
- newValue1 += parcel1;
- T newValue2 = T(value);
- if (!needToPreventUnderflow)
- newValue2 += parcel2;
-
- if (!needToPreventOverflow) {
QCOMPARE(atomic.fetchAndAddRelaxed(parcel1), T(value));
QCOMPARE(atomic.loadRelaxed(), newValue1);
QCOMPARE(atomic.fetchAndAddRelaxed(parcel2), newValue1);
- }
QCOMPARE(atomic.loadRelaxed(), T(value));
- if (!needToPreventUnderflow) {
QCOMPARE(atomic.fetchAndAddRelaxed(parcel2), T(value));
QCOMPARE(atomic.loadRelaxed(), newValue2);
QCOMPARE(atomic.fetchAndAddRelaxed(parcel1), newValue2);
- }
QCOMPARE(atomic.loadRelaxed(), T(value));
- if (!needToPreventOverflow) {
QCOMPARE(atomic.fetchAndAddAcquire(parcel1), T(value));
QCOMPARE(atomic.loadRelaxed(), newValue1);
QCOMPARE(atomic.fetchAndAddAcquire(parcel2), newValue1);
- }
QCOMPARE(atomic.loadRelaxed(), T(value));
- if (!needToPreventUnderflow) {
QCOMPARE(atomic.fetchAndAddAcquire(parcel2), T(value));
QCOMPARE(atomic.loadRelaxed(), newValue2);
QCOMPARE(atomic.fetchAndAddAcquire(parcel1), newValue2);
- }
QCOMPARE(atomic.loadRelaxed(), T(value));
- if (!needToPreventOverflow) {
QCOMPARE(atomic.fetchAndAddRelease(parcel1), T(value));
QCOMPARE(atomic.loadAcquire(), newValue1);
QCOMPARE(atomic.fetchAndAddRelease(parcel2), newValue1);
- }
QCOMPARE(atomic.loadAcquire(), T(value));
- if (!needToPreventUnderflow) {
QCOMPARE(atomic.fetchAndAddRelease(parcel2), T(value));
QCOMPARE(atomic.loadAcquire(), newValue2);
QCOMPARE(atomic.fetchAndAddRelease(parcel1), newValue2);
- }
QCOMPARE(atomic.loadAcquire(), T(value));
- if (!needToPreventOverflow) {
QCOMPARE(atomic.fetchAndAddOrdered(parcel1), T(value));
QCOMPARE(atomic.loadAcquire(), newValue1);
QCOMPARE(atomic.fetchAndAddOrdered(parcel2), newValue1);
- }
QCOMPARE(atomic.loadAcquire(), T(value));
- if (!needToPreventUnderflow) {
QCOMPARE(atomic.fetchAndAddOrdered(parcel2), T(value));
QCOMPARE(atomic.loadAcquire(), newValue2);
QCOMPARE(atomic.fetchAndAddOrdered(parcel1), newValue2);
- }
QCOMPARE(atomic.loadAcquire(), T(value));
// operator+=
- if (!needToPreventOverflow) {
QCOMPARE(atomic += parcel1, newValue1);
QCOMPARE(atomic += parcel2, T(value));
- }
- if (!needToPreventUnderflow) {
QCOMPARE(atomic += parcel2, newValue2);
QCOMPARE(atomic += parcel1, T(value));
- }
}
void tst_QAtomicIntegerXX::fetchAndSub()
@@ -565,80 +476,55 @@ void tst_QAtomicIntegerXX::fetchAndSub()
QFETCH(LargeInt, value);
QAtomicInteger<T> atomic(value);
+ // We perform the subtractions using the unsigned type U to avoid signed
+ // integer underrflows in the non-atomic portion (atomics have well-defined,
+ // two's complement underflow, even signed ones).
T parcel1 = 42;
T parcel2 = T(0-parcel1);
+ T newValue1 = T(U(value) - parcel1);
+ T newValue2 = T(U(value) - parcel2);
- const bool needToPreventOverflow = TypeIsSigned && value > std::numeric_limits<T>::max() - parcel1;
- const bool needToPreventUnderflow = TypeIsSigned && value < std::numeric_limits<T>::min() - parcel2;
-
- T newValue1 = T(value);
- if (!needToPreventUnderflow)
- newValue1 -= parcel1;
- T newValue2 = T(value);
- if (!needToPreventOverflow)
- newValue2 -= parcel2;
-
- if (!needToPreventUnderflow) {
QCOMPARE(atomic.fetchAndSubRelaxed(parcel1), T(value));
QCOMPARE(atomic.loadRelaxed(), newValue1);
QCOMPARE(atomic.fetchAndSubRelaxed(parcel2), newValue1);
- }
QCOMPARE(atomic.loadRelaxed(), T(value));
- if (!needToPreventOverflow) {
QCOMPARE(atomic.fetchAndSubRelaxed(parcel2), T(value));
QCOMPARE(atomic.loadRelaxed(), newValue2);
QCOMPARE(atomic.fetchAndSubRelaxed(parcel1), newValue2);
- }
QCOMPARE(atomic.loadRelaxed(), T(value));
- if (!needToPreventUnderflow) {
QCOMPARE(atomic.fetchAndSubAcquire(parcel1), T(value));
QCOMPARE(atomic.loadRelaxed(), newValue1);
QCOMPARE(atomic.fetchAndSubAcquire(parcel2), newValue1);
- }
QCOMPARE(atomic.loadRelaxed(), T(value));
- if (!needToPreventOverflow) {
QCOMPARE(atomic.fetchAndSubAcquire(parcel2), T(value));
QCOMPARE(atomic.loadRelaxed(), newValue2);
QCOMPARE(atomic.fetchAndSubAcquire(parcel1), newValue2);
- }
QCOMPARE(atomic.loadRelaxed(), T(value));
- if (!needToPreventUnderflow) {
QCOMPARE(atomic.fetchAndSubRelease(parcel1), T(value));
QCOMPARE(atomic.loadAcquire(), newValue1);
QCOMPARE(atomic.fetchAndSubRelease(parcel2), newValue1);
- }
QCOMPARE(atomic.loadAcquire(), T(value));
- if (!needToPreventOverflow) {
QCOMPARE(atomic.fetchAndSubRelease(parcel2), T(value));
QCOMPARE(atomic.loadAcquire(), newValue2);
QCOMPARE(atomic.fetchAndSubRelease(parcel1), newValue2);
- }
QCOMPARE(atomic.loadAcquire(), T(value));
- if (!needToPreventUnderflow) {
QCOMPARE(atomic.fetchAndSubOrdered(parcel1), T(value));
QCOMPARE(atomic.loadAcquire(), newValue1);
QCOMPARE(atomic.fetchAndSubOrdered(parcel2), newValue1);
- }
QCOMPARE(atomic.loadAcquire(), T(value));
- if (!needToPreventOverflow) {
QCOMPARE(atomic.fetchAndSubOrdered(parcel2), T(value));
QCOMPARE(atomic.loadAcquire(), newValue2);
QCOMPARE(atomic.fetchAndSubOrdered(parcel1), newValue2);
- }
QCOMPARE(atomic.loadAcquire(), T(value));
// operator-=
- if (!needToPreventUnderflow) {
QCOMPARE(atomic -= parcel1, newValue1);
QCOMPARE(atomic -= parcel2, T(value));
- }
- if (!needToPreventOverflow) {
QCOMPARE(atomic -= parcel2, newValue2);
QCOMPARE(atomic -= parcel1, T(value));
- }
}
void tst_QAtomicIntegerXX::fetchAndOr()
@@ -788,8 +674,9 @@ void tst_QAtomicIntegerXX::fetchAndXor()
QCOMPARE(atomic ^= minusOne, T(~value));
QCOMPARE(atomic ^= minusOne, T(value));
}
-
-#include "tst_qatomicinteger.moc"
+}
QTEST_APPLESS_MAIN(tst_QAtomicIntegerXX)
+#include "tst_qatomicinteger.moc"
+