summaryrefslogtreecommitdiffstats
path: root/tests/auto/corelib/thread
diff options
context:
space:
mode:
authorThiago Macieira <thiago.macieira@intel.com>2012-08-06 19:57:59 +0200
committerThe Qt Project <gerrit-noreply@qt-project.org>2014-02-16 05:12:26 +0100
commit634f82f1f1fda7983abf70b58e43c580b1f01df0 (patch)
tree0d3b67615c35f6c8938b0d40c2ab59097a4001ea /tests/auto/corelib/thread
parentfb30a3dd7c2e449235ac5896877bbc0ad41a3835 (diff)
Add a testAndSet overload to the atomics that returns the current value
This is extremely useful, since the most common action after a failed compare-and-swap is to loop around, trying again with the current value as found in memory. Code currently written as: do { Type value = atomic.load(); ... } while (!atomic.testAndSetRelaxed(value, desired)); Becomes: Type value = atomic.load(); do { ... } while (!atomic.testAndSetRelaxed(value, desired, value)); In most CPU architectures, the value that was found in memory is known to the compare-and-swap code, so this is more efficient than the previous code. In architectures where the value is not known, the new code is no worse than before. The implementation sometimes modified an existing function, sometimes it added a new one, depending on whether more registers were needed in the assembly (like ARMv6-7), the code became more complex (ARMv5), the optimizer failed (C++11), or it was just plain equivalent (MIPS). Change-Id: I7d6d200ea9746ec8978a0c1e1969dbc3580b9285 Reviewed-by: Oswald Buddenhagen <oswald.buddenhagen@digia.com> Reviewed-by: Lars Knoll <lars.knoll@digia.com> Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
Diffstat (limited to 'tests/auto/corelib/thread')
-rw-r--r--tests/auto/corelib/thread/qatomicint/tst_qatomicint.cpp91
-rw-r--r--tests/auto/corelib/thread/qatomicinteger/tst_qatomicinteger.cpp382
-rw-r--r--tests/auto/corelib/thread/qatomicpointer/tst_qatomicpointer.cpp53
3 files changed, 525 insertions, 1 deletions
diff --git a/tests/auto/corelib/thread/qatomicint/tst_qatomicint.cpp b/tests/auto/corelib/thread/qatomicint/tst_qatomicint.cpp
index 42b3a52531..f0d817d37d 100644
--- a/tests/auto/corelib/thread/qatomicint/tst_qatomicint.cpp
+++ b/tests/auto/corelib/thread/qatomicint/tst_qatomicint.cpp
@@ -84,6 +84,8 @@ private slots:
void fetchAndAdd_data();
void fetchAndAdd();
+ void operators();
+
// stress tests
void testAndSet_loop();
void fetchAndAdd_loop();
@@ -540,6 +542,43 @@ void tst_QAtomicInt::testAndSet()
QAtomicInt atomic = value;
QTEST(atomic.testAndSetOrdered(expected, newval) ? 1 : 0, "result");
}
+
+#ifdef Q_ATOMIC_INT32_IS_SUPPORTED
+ QFETCH(int, result);
+ // the new implementation has the version that loads the current value
+
+ {
+ QAtomicInt atomic = value;
+ int currentval = 0xdeadbeef;
+ QCOMPARE(atomic.testAndSetRelaxed(expected, newval, currentval), result);
+ if (!result)
+ QCOMPARE(currentval, value);
+ }
+
+ {
+ QAtomicInt atomic = value;
+ int currentval = 0xdeadbeef;
+ QCOMPARE(atomic.testAndSetAcquire(expected, newval, currentval), result);
+ if (!result)
+ QCOMPARE(currentval, value);
+ }
+
+ {
+ QAtomicInt atomic = value;
+ int currentval = 0xdeadbeef;
+ QCOMPARE(atomic.testAndSetRelease(expected, newval, currentval), result);
+ if (!result)
+ QCOMPARE(currentval, value);
+ }
+
+ {
+ QAtomicInt atomic = value;
+ int currentval = 0xdeadbeef;
+ QCOMPARE(atomic.testAndSetOrdered(expected, newval, currentval), result);
+ if (!result)
+ QCOMPARE(currentval, value);
+ }
+#endif
}
void tst_QAtomicInt::isFetchAndStoreNative()
@@ -770,6 +809,58 @@ void tst_QAtomicInt::fetchAndAdd()
}
}
+void tst_QAtomicInt::operators()
+{
+ {
+ // Test that QBasicAtomicInt also has operator= and cast operators
+ // We've been using them for QAtomicInt elsewhere
+ QBasicAtomicInt atomic = Q_BASIC_ATOMIC_INITIALIZER(0);
+ atomic = 1;
+ QCOMPARE(int(atomic), 1);
+ }
+
+ QAtomicInt atomic = 0;
+ int x = ++atomic;
+ QCOMPARE(int(atomic), x);
+ QCOMPARE(int(atomic), 1);
+
+ x = atomic++;
+ QCOMPARE(int(atomic), x + 1);
+ QCOMPARE(int(atomic), 2);
+
+ x = atomic--;
+ QCOMPARE(int(atomic), x - 1);
+ QCOMPARE(int(atomic), 1);
+
+ x = --atomic;
+ QCOMPARE(int(atomic), x);
+ QCOMPARE(int(atomic), 0);
+
+ x = (atomic += 1);
+ QCOMPARE(int(atomic), x);
+ QCOMPARE(int(atomic), 1);
+
+ x = (atomic -= 1);
+ QCOMPARE(int(atomic), x);
+ QCOMPARE(int(atomic), 0);
+
+ x = (atomic |= 0xf);
+ QCOMPARE(int(atomic), x);
+ QCOMPARE(int(atomic), 0xf);
+
+ x = (atomic &= 0x17);
+ QCOMPARE(int(atomic), x);
+ QCOMPARE(int(atomic), 7);
+
+ x = (atomic ^= 0x14);
+ QCOMPARE(int(atomic), x);
+ QCOMPARE(int(atomic), 0x13);
+
+ x = (atomic ^= atomic);
+ QCOMPARE(int(atomic), x);
+ QCOMPARE(int(atomic), 0);
+}
+
void tst_QAtomicInt::testAndSet_loop()
{
QTime stopWatch;
diff --git a/tests/auto/corelib/thread/qatomicinteger/tst_qatomicinteger.cpp b/tests/auto/corelib/thread/qatomicinteger/tst_qatomicinteger.cpp
index a7139b6a9a..6ddd2ff233 100644
--- a/tests/auto/corelib/thread/qatomicinteger/tst_qatomicinteger.cpp
+++ b/tests/auto/corelib/thread/qatomicinteger/tst_qatomicinteger.cpp
@@ -143,6 +143,9 @@ private Q_SLOTS:
void assign_data() { addData(); }
void assign();
+ void operatorInteger_data() { addData(); }
+ void operatorInteger();
+
void loadAcquireStoreRelease_data() { addData(); }
void loadAcquireStoreRelease();
@@ -152,11 +155,29 @@ private Q_SLOTS:
void testAndSet_data() { addData(); }
void testAndSet();
+ void testAndSet3_data() { addData(); }
+ void testAndSet3();
+
void fetchAndStore_data() { addData(); }
void fetchAndStore();
void fetchAndAdd_data() { addData(); }
void fetchAndAdd();
+
+ void fetchAndSub_data() { addData(); }
+ void fetchAndSub();
+
+ void addSub_data() { addData(); }
+ void addSub();
+
+ void fetchAndOr_data() { addData(); }
+ void fetchAndOr();
+
+ void fetchAndAnd_data() { addData(); }
+ void fetchAndAnd();
+
+ void fetchAndXor_data() { addData(); }
+ void fetchAndXor();
};
template <bool> inline void booleanHelper() { }
@@ -285,9 +306,13 @@ void tst_QAtomicIntegerXX::assign()
QCOMPARE(copy.load(), atomic.load());
QAtomicInteger<T> copy2;
- copy2 = atomic;
+ copy2 = atomic; // operator=(const QAtomicInteger &)
QCOMPARE(copy2.load(), atomic.load());
+ QAtomicInteger<T> copy2bis;
+ copy2bis = atomic.load(); // operator=(T)
+ QCOMPARE(copy2bis.load(), atomic.load());
+
// move
QAtomicInteger<T> copy3;
copy3 = qMove(copy);
@@ -298,6 +323,16 @@ void tst_QAtomicIntegerXX::assign()
QCOMPARE(copy4.load(), atomic.load());
}
+void tst_QAtomicIntegerXX::operatorInteger()
+{
+ QFETCH(LargeInt, value);
+
+ QAtomicInteger<T> atomic(value);
+ T val2 = atomic;
+ QCOMPARE(val2, atomic.load());
+ QCOMPARE(val2, T(value));
+}
+
void tst_QAtomicIntegerXX::loadAcquireStoreRelease()
{
QFETCH(LargeInt, value);
@@ -327,6 +362,17 @@ void tst_QAtomicIntegerXX::refDeref()
QCOMPARE(atomic.load(), prevValue);
QCOMPARE(atomic.ref(), (value != 0));
QCOMPARE(atomic.load(), T(value));
+
+ QCOMPARE(++atomic, nextValue);
+ QCOMPARE(--atomic, T(value));
+ QCOMPARE(--atomic, prevValue);
+ QCOMPARE(++atomic, T(value));
+
+ QCOMPARE(atomic++, T(value));
+ QCOMPARE(atomic--, nextValue);
+ QCOMPARE(atomic--, T(value));
+ QCOMPARE(atomic++, prevValue);
+ QCOMPARE(atomic.load(), T(value));
}
void tst_QAtomicIntegerXX::testAndSet()
@@ -360,6 +406,42 @@ void tst_QAtomicIntegerXX::testAndSet()
QCOMPARE(atomic.loadAcquire(), T(value));
}
+void tst_QAtomicIntegerXX::testAndSet3()
+{
+ QFETCH(LargeInt, value);
+ T newValue = ~T(value);
+ T oldValue;
+ QAtomicInteger<T> atomic(value);
+
+ QVERIFY(atomic.testAndSetRelaxed(value, newValue, oldValue));
+ QCOMPARE(atomic.load(), newValue);
+ QVERIFY(!atomic.testAndSetRelaxed(value, newValue, oldValue));
+ QCOMPARE(oldValue, newValue);
+ QVERIFY(atomic.testAndSetRelaxed(newValue, value, oldValue));
+ QCOMPARE(atomic.load(), T(value));
+
+ QVERIFY(atomic.testAndSetAcquire(value, newValue, oldValue));
+ QCOMPARE(atomic.load(), newValue);
+ QVERIFY(!atomic.testAndSetAcquire(value, newValue, oldValue));
+ QCOMPARE(oldValue, newValue);
+ QVERIFY(atomic.testAndSetAcquire(newValue, value, oldValue));
+ QCOMPARE(atomic.load(), T(value));
+
+ QVERIFY(atomic.testAndSetRelease(value, newValue, oldValue));
+ QCOMPARE(atomic.loadAcquire(), newValue);
+ QVERIFY(!atomic.testAndSetRelease(value, newValue, oldValue));
+ QCOMPARE(oldValue, newValue);
+ QVERIFY(atomic.testAndSetRelease(newValue, value, oldValue));
+ QCOMPARE(atomic.loadAcquire(), T(value));
+
+ QVERIFY(atomic.testAndSetOrdered(value, newValue, oldValue));
+ QCOMPARE(atomic.loadAcquire(), newValue);
+ QVERIFY(!atomic.testAndSetOrdered(value, newValue, oldValue));
+ QCOMPARE(oldValue, newValue);
+ QVERIFY(atomic.testAndSetOrdered(newValue, value, oldValue));
+ QCOMPARE(atomic.loadAcquire(), T(value));
+}
+
void tst_QAtomicIntegerXX::fetchAndStore()
{
QFETCH(LargeInt, value);
@@ -433,6 +515,304 @@ void tst_QAtomicIntegerXX::fetchAndAdd()
QCOMPARE(atomic.loadAcquire(), newValue2);
QCOMPARE(atomic.fetchAndAddOrdered(parcel1), newValue2);
QCOMPARE(atomic.loadAcquire(), T(value));
+
+ // operator+=
+ QCOMPARE(atomic += parcel1, newValue1);
+ QCOMPARE(atomic += parcel2, T(value));
+ QCOMPARE(atomic += parcel2, newValue2);
+ QCOMPARE(atomic += parcel1, T(value));
+}
+
+void tst_QAtomicIntegerXX::fetchAndSub()
+{
+ 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.fetchAndSubRelaxed(parcel1), T(value));
+ QCOMPARE(atomic.load(), newValue1);
+ QCOMPARE(atomic.fetchAndSubRelaxed(parcel2), newValue1);
+ QCOMPARE(atomic.load(), T(value));
+ QCOMPARE(atomic.fetchAndSubRelaxed(parcel2), T(value));
+ QCOMPARE(atomic.load(), newValue2);
+ QCOMPARE(atomic.fetchAndSubRelaxed(parcel1), newValue2);
+ QCOMPARE(atomic.load(), T(value));
+
+ QCOMPARE(atomic.fetchAndSubAcquire(parcel1), T(value));
+ QCOMPARE(atomic.load(), newValue1);
+ QCOMPARE(atomic.fetchAndSubAcquire(parcel2), newValue1);
+ QCOMPARE(atomic.load(), T(value));
+ QCOMPARE(atomic.fetchAndSubAcquire(parcel2), T(value));
+ QCOMPARE(atomic.load(), newValue2);
+ QCOMPARE(atomic.fetchAndSubAcquire(parcel1), newValue2);
+ QCOMPARE(atomic.load(), T(value));
+
+ QCOMPARE(atomic.fetchAndSubRelease(parcel1), T(value));
+ QCOMPARE(atomic.loadAcquire(), newValue1);
+ QCOMPARE(atomic.fetchAndSubRelease(parcel2), newValue1);
+ QCOMPARE(atomic.loadAcquire(), T(value));
+ QCOMPARE(atomic.fetchAndSubRelease(parcel2), T(value));
+ QCOMPARE(atomic.loadAcquire(), newValue2);
+ QCOMPARE(atomic.fetchAndSubRelease(parcel1), newValue2);
+ QCOMPARE(atomic.loadAcquire(), T(value));
+
+ QCOMPARE(atomic.fetchAndSubOrdered(parcel1), T(value));
+ QCOMPARE(atomic.loadAcquire(), newValue1);
+ QCOMPARE(atomic.fetchAndSubOrdered(parcel2), newValue1);
+ QCOMPARE(atomic.loadAcquire(), T(value));
+ QCOMPARE(atomic.fetchAndSubOrdered(parcel2), T(value));
+ QCOMPARE(atomic.loadAcquire(), newValue2);
+ QCOMPARE(atomic.fetchAndSubOrdered(parcel1), newValue2);
+ QCOMPARE(atomic.loadAcquire(), T(value));
+
+ // operator-=
+ QCOMPARE(atomic -= parcel1, newValue1);
+ QCOMPARE(atomic -= parcel2, T(value));
+ QCOMPARE(atomic -= parcel2, newValue2);
+ QCOMPARE(atomic -= parcel1, T(value));
+}
+
+void tst_QAtomicIntegerXX::addSub()
+{
+ 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) - parcel1;
+
+ QCOMPARE(atomic.fetchAndAddRelaxed(parcel1), T(value));
+ QCOMPARE(atomic.load(), newValue1);
+ QCOMPARE(atomic.fetchAndSubRelaxed(parcel1), newValue1);
+ QCOMPARE(atomic.load(), T(value));
+ QCOMPARE(atomic.fetchAndSubRelaxed(parcel1), T(value));
+ QCOMPARE(atomic.load(), newValue2);
+ QCOMPARE(atomic.fetchAndAddRelaxed(parcel1), newValue2);
+ QCOMPARE(atomic.load(), T(value));
+ QCOMPARE(atomic.fetchAndAddRelaxed(parcel2), T(value));
+ QCOMPARE(atomic.load(), newValue2);
+ QCOMPARE(atomic.fetchAndSubRelaxed(parcel2), newValue2);
+ QCOMPARE(atomic.load(), T(value));
+ QCOMPARE(atomic.fetchAndSubRelaxed(parcel2), T(value));
+ QCOMPARE(atomic.load(), newValue1);
+ QCOMPARE(atomic.fetchAndAddRelaxed(parcel2), newValue1);
+ QCOMPARE(atomic.load(), T(value));
+
+ QCOMPARE(atomic.fetchAndAddAcquire(parcel1), T(value));
+ QCOMPARE(atomic.load(), newValue1);
+ QCOMPARE(atomic.fetchAndSubAcquire(parcel1), newValue1);
+ QCOMPARE(atomic.load(), T(value));
+ QCOMPARE(atomic.fetchAndSubAcquire(parcel1), T(value));
+ QCOMPARE(atomic.load(), newValue2);
+ QCOMPARE(atomic.fetchAndAddAcquire(parcel1), newValue2);
+ QCOMPARE(atomic.load(), T(value));
+ QCOMPARE(atomic.fetchAndAddAcquire(parcel2), T(value));
+ QCOMPARE(atomic.load(), newValue2);
+ QCOMPARE(atomic.fetchAndSubAcquire(parcel2), newValue2);
+ QCOMPARE(atomic.load(), T(value));
+ QCOMPARE(atomic.fetchAndSubAcquire(parcel2), T(value));
+ QCOMPARE(atomic.load(), newValue1);
+ QCOMPARE(atomic.fetchAndAddAcquire(parcel2), newValue1);
+ QCOMPARE(atomic.load(), T(value));
+
+ QCOMPARE(atomic.fetchAndAddRelease(parcel1), T(value));
+ QCOMPARE(atomic.load(), newValue1);
+ QCOMPARE(atomic.fetchAndSubRelease(parcel1), newValue1);
+ QCOMPARE(atomic.load(), T(value));
+ QCOMPARE(atomic.fetchAndSubRelease(parcel1), T(value));
+ QCOMPARE(atomic.load(), newValue2);
+ QCOMPARE(atomic.fetchAndAddRelease(parcel1), newValue2);
+ QCOMPARE(atomic.load(), T(value));
+ QCOMPARE(atomic.fetchAndAddRelease(parcel2), T(value));
+ QCOMPARE(atomic.load(), newValue2);
+ QCOMPARE(atomic.fetchAndSubRelease(parcel2), newValue2);
+ QCOMPARE(atomic.load(), T(value));
+ QCOMPARE(atomic.fetchAndSubRelease(parcel2), T(value));
+ QCOMPARE(atomic.load(), newValue1);
+ QCOMPARE(atomic.fetchAndAddRelease(parcel2), newValue1);
+ QCOMPARE(atomic.load(), T(value));
+
+ QCOMPARE(atomic.fetchAndAddOrdered(parcel1), T(value));
+ QCOMPARE(atomic.load(), newValue1);
+ QCOMPARE(atomic.fetchAndSubOrdered(parcel1), newValue1);
+ QCOMPARE(atomic.load(), T(value));
+ QCOMPARE(atomic.fetchAndSubOrdered(parcel1), T(value));
+ QCOMPARE(atomic.load(), newValue2);
+ QCOMPARE(atomic.fetchAndAddOrdered(parcel1), newValue2);
+ QCOMPARE(atomic.load(), T(value));
+ QCOMPARE(atomic.fetchAndAddOrdered(parcel2), T(value));
+ QCOMPARE(atomic.load(), newValue2);
+ QCOMPARE(atomic.fetchAndSubOrdered(parcel2), newValue2);
+ QCOMPARE(atomic.load(), T(value));
+ QCOMPARE(atomic.fetchAndSubOrdered(parcel2), T(value));
+ QCOMPARE(atomic.load(), newValue1);
+ QCOMPARE(atomic.fetchAndAddOrdered(parcel2), newValue1);
+ QCOMPARE(atomic.load(), T(value));
+
+ // operator+= and operator-=
+ QCOMPARE(atomic += parcel1, newValue1);
+ QCOMPARE(atomic -= parcel1, T(value));
+ QCOMPARE(atomic -= parcel1, newValue2);
+ QCOMPARE(atomic += parcel1, T(value));
+ QCOMPARE(atomic += parcel2, newValue2);
+ QCOMPARE(atomic -= parcel2, T(value));
+ QCOMPARE(atomic -= parcel2, newValue1);
+ QCOMPARE(atomic += parcel2, T(value));
+}
+
+void tst_QAtomicIntegerXX::fetchAndOr()
+{
+ QFETCH(LargeInt, value);
+ QAtomicInteger<T> atomic(value);
+
+ T zero = 0;
+ T one = 1;
+ T minusOne = T(~0);
+
+ QCOMPARE(atomic.fetchAndOrRelaxed(zero), T(value));
+ QCOMPARE(atomic.fetchAndOrRelaxed(one), T(value));
+ QCOMPARE(atomic.load(), T(value | 1));
+ QCOMPARE(atomic.fetchAndOrRelaxed(minusOne), T(value | 1));
+ QCOMPARE(atomic.load(), minusOne);
+
+ atomic.store(value);
+ QCOMPARE(atomic.fetchAndOrAcquire(zero), T(value));
+ QCOMPARE(atomic.fetchAndOrAcquire(one), T(value));
+ QCOMPARE(atomic.load(), T(value | 1));
+ QCOMPARE(atomic.fetchAndOrAcquire(minusOne), T(value | 1));
+ QCOMPARE(atomic.load(), minusOne);
+
+ atomic.store(value);
+ QCOMPARE(atomic.fetchAndOrRelease(zero), T(value));
+ QCOMPARE(atomic.fetchAndOrRelease(one), T(value));
+ QCOMPARE(atomic.load(), T(value | 1));
+ QCOMPARE(atomic.fetchAndOrRelease(minusOne), T(value | 1));
+ QCOMPARE(atomic.load(), minusOne);
+
+ atomic.store(value);
+ QCOMPARE(atomic.fetchAndOrOrdered(zero), T(value));
+ QCOMPARE(atomic.fetchAndOrOrdered(one), T(value));
+ QCOMPARE(atomic.load(), T(value | 1));
+ QCOMPARE(atomic.fetchAndOrOrdered(minusOne), T(value | 1));
+ QCOMPARE(atomic.load(), minusOne);
+
+ atomic.store(value);
+ QCOMPARE(atomic |= zero, T(value));
+ QCOMPARE(atomic |= one, T(value | 1));
+ QCOMPARE(atomic |= minusOne, minusOne);
+}
+
+void tst_QAtomicIntegerXX::fetchAndAnd()
+{
+ QFETCH(LargeInt, value);
+ QAtomicInteger<T> atomic(value);
+
+ T zero = 0;
+ T f = 0xf;
+ T minusOne = T(~0);
+
+ QCOMPARE(atomic.fetchAndAndRelaxed(minusOne), T(value));
+ QCOMPARE(atomic.load(), T(value));
+ QCOMPARE(atomic.fetchAndAndRelaxed(f), T(value));
+ QCOMPARE(atomic.load(), T(value & 0xf));
+ QCOMPARE(atomic.fetchAndAndRelaxed(zero), T(value & 0xf));
+ QCOMPARE(atomic.load(), zero);
+
+ atomic.store(value);
+ QCOMPARE(atomic.fetchAndAndAcquire(minusOne), T(value));
+ QCOMPARE(atomic.load(), T(value));
+ QCOMPARE(atomic.fetchAndAndAcquire(f), T(value));
+ QCOMPARE(atomic.load(), T(value & 0xf));
+ QCOMPARE(atomic.fetchAndAndAcquire(zero), T(value & 0xf));
+ QCOMPARE(atomic.load(), zero);
+
+ atomic.store(value);
+ QCOMPARE(atomic.fetchAndAndRelease(minusOne), T(value));
+ QCOMPARE(atomic.load(), T(value));
+ QCOMPARE(atomic.fetchAndAndRelease(f), T(value));
+ QCOMPARE(atomic.load(), T(value & 0xf));
+ QCOMPARE(atomic.fetchAndAndRelease(zero), T(value & 0xf));
+ QCOMPARE(atomic.load(), zero);
+
+ atomic.store(value);
+ QCOMPARE(atomic.fetchAndAndOrdered(minusOne), T(value));
+ QCOMPARE(atomic.load(), T(value));
+ QCOMPARE(atomic.fetchAndAndOrdered(f), T(value));
+ QCOMPARE(atomic.load(), T(value & 0xf));
+ QCOMPARE(atomic.fetchAndAndOrdered(zero), T(value & 0xf));
+ QCOMPARE(atomic.load(), zero);
+
+ atomic.store(value);
+ QCOMPARE(atomic &= minusOne, T(value));
+ QCOMPARE(atomic &= f, T(value & 0xf));
+ QCOMPARE(atomic &= zero, zero);
+}
+
+void tst_QAtomicIntegerXX::fetchAndXor()
+{
+ QFETCH(LargeInt, value);
+ QAtomicInteger<T> atomic(value);
+
+ T zero = 0;
+ T pattern = T(Q_UINT64_C(0xcccccccccccccccc));
+ T minusOne = T(~0);
+
+ QCOMPARE(atomic.fetchAndXorRelaxed(zero), T(value));
+ QCOMPARE(atomic.load(), T(value));
+ QCOMPARE(atomic.fetchAndXorRelaxed(pattern), T(value));
+ QCOMPARE(atomic.load(), T(value ^ pattern));
+ QCOMPARE(atomic.fetchAndXorRelaxed(pattern), T(value ^ pattern));
+ QCOMPARE(atomic.load(), T(value));
+ QCOMPARE(atomic.fetchAndXorRelaxed(minusOne), T(value));
+ QCOMPARE(atomic.load(), T(~value));
+ QCOMPARE(atomic.fetchAndXorRelaxed(minusOne), T(~value));
+ QCOMPARE(atomic.load(), T(value));
+
+ QCOMPARE(atomic.fetchAndXorAcquire(zero), T(value));
+ QCOMPARE(atomic.load(), T(value));
+ QCOMPARE(atomic.fetchAndXorAcquire(pattern), T(value));
+ QCOMPARE(atomic.load(), T(value ^ pattern));
+ QCOMPARE(atomic.fetchAndXorAcquire(pattern), T(value ^ pattern));
+ QCOMPARE(atomic.load(), T(value));
+ QCOMPARE(atomic.fetchAndXorAcquire(minusOne), T(value));
+ QCOMPARE(atomic.load(), T(~value));
+ QCOMPARE(atomic.fetchAndXorAcquire(minusOne), T(~value));
+ QCOMPARE(atomic.load(), T(value));
+
+ QCOMPARE(atomic.fetchAndXorRelease(zero), T(value));
+ QCOMPARE(atomic.load(), T(value));
+ QCOMPARE(atomic.fetchAndXorRelease(pattern), T(value));
+ QCOMPARE(atomic.load(), T(value ^ pattern));
+ QCOMPARE(atomic.fetchAndXorRelease(pattern), T(value ^ pattern));
+ QCOMPARE(atomic.load(), T(value));
+ QCOMPARE(atomic.fetchAndXorRelease(minusOne), T(value));
+ QCOMPARE(atomic.load(), T(~value));
+ QCOMPARE(atomic.fetchAndXorRelease(minusOne), T(~value));
+ QCOMPARE(atomic.load(), T(value));
+
+ QCOMPARE(atomic.fetchAndXorOrdered(zero), T(value));
+ QCOMPARE(atomic.load(), T(value));
+ QCOMPARE(atomic.fetchAndXorOrdered(pattern), T(value));
+ QCOMPARE(atomic.load(), T(value ^ pattern));
+ QCOMPARE(atomic.fetchAndXorOrdered(pattern), T(value ^ pattern));
+ QCOMPARE(atomic.load(), T(value));
+ QCOMPARE(atomic.fetchAndXorOrdered(minusOne), T(value));
+ QCOMPARE(atomic.load(), T(~value));
+ QCOMPARE(atomic.fetchAndXorOrdered(minusOne), T(~value));
+ QCOMPARE(atomic.load(), T(value));
+
+ QCOMPARE(atomic ^= zero, T(value));
+ QCOMPARE(atomic ^= pattern, T(value ^ pattern));
+ QCOMPARE(atomic ^= pattern, T(value));
+ QCOMPARE(atomic ^= minusOne, T(~value));
+ QCOMPARE(atomic ^= minusOne, T(value));
}
#include "tst_qatomicinteger.moc"
diff --git a/tests/auto/corelib/thread/qatomicpointer/tst_qatomicpointer.cpp b/tests/auto/corelib/thread/qatomicpointer/tst_qatomicpointer.cpp
index d4e777e35b..595808e270 100644
--- a/tests/auto/corelib/thread/qatomicpointer/tst_qatomicpointer.cpp
+++ b/tests/auto/corelib/thread/qatomicpointer/tst_qatomicpointer.cpp
@@ -70,6 +70,8 @@ private slots:
void constAndVolatile();
void forwardDeclared();
+
+ void operators();
private:
static void warningFreeHelper();
};
@@ -664,5 +666,56 @@ void tst_QAtomicPointer::forwardDeclared()
QVERIFY(true);
}
+template <typename T> static void operators_helper()
+{
+ typedef T *Ptr;
+ T array[3] = {};
+ Ptr zero = array;
+ Ptr one = array + 1;
+ Ptr two = array + 2;
+
+ {
+ // Test that QBasicAtomicPointer also has operator= and cast operators
+ // We've been using them for QAtomicPointer<T> elsewhere
+ QBasicAtomicPointer<T> atomic = Q_BASIC_ATOMIC_INITIALIZER(0);
+ atomic = one;
+ QCOMPARE(Ptr(atomic), one);
+ }
+
+ QAtomicPointer<T> atomic = zero;
+ Ptr x = ++atomic;
+ QCOMPARE(Ptr(atomic), x);
+ QCOMPARE(Ptr(atomic), one);
+
+ x = atomic++;
+ QCOMPARE(Ptr(atomic), x + 1);
+ QCOMPARE(Ptr(atomic), two);
+
+ x = atomic--;
+ QCOMPARE(Ptr(atomic), x - 1);
+ QCOMPARE(Ptr(atomic), one);
+
+ x = --atomic;
+ QCOMPARE(Ptr(atomic), x);
+ QCOMPARE(Ptr(atomic), zero);
+
+ x = (atomic += 1);
+ QCOMPARE(Ptr(atomic), x);
+ QCOMPARE(Ptr(atomic), one);
+
+ x = (atomic -= 1);
+ QCOMPARE(Ptr(atomic), x);
+ QCOMPARE(Ptr(atomic), zero);
+}
+
+struct Big { double d[10]; };
+void tst_QAtomicPointer::operators()
+{
+ operators_helper<char>();
+ operators_helper<int>();
+ operators_helper<double>();
+ operators_helper<Big>();
+}
+
QTEST_APPLESS_MAIN(tst_QAtomicPointer)
#include "tst_qatomicpointer.moc"