summaryrefslogtreecommitdiffstats
path: root/tests/auto/corelib/thread
diff options
context:
space:
mode:
Diffstat (limited to 'tests/auto/corelib/thread')
-rw-r--r--tests/auto/corelib/thread/qmutex/qmutex.pro1
-rw-r--r--tests/auto/corelib/thread/qmutex/tst_qmutex.cpp1179
-rw-r--r--tests/auto/corelib/thread/qsemaphore/tst_qsemaphore.cpp6
-rw-r--r--tests/auto/corelib/thread/qthread/tst_qthread.cpp20
-rw-r--r--tests/auto/corelib/thread/qthreadonce/tst_qthreadonce.cpp2
-rw-r--r--tests/auto/corelib/thread/qthreadstorage/tst_qthreadstorage.cpp24
6 files changed, 952 insertions, 280 deletions
diff --git a/tests/auto/corelib/thread/qmutex/qmutex.pro b/tests/auto/corelib/thread/qmutex/qmutex.pro
index 229e57eb89..cb9d364b71 100644
--- a/tests/auto/corelib/thread/qmutex/qmutex.pro
+++ b/tests/auto/corelib/thread/qmutex/qmutex.pro
@@ -2,3 +2,4 @@ CONFIG += testcase
TARGET = tst_qmutex
QT = core testlib
SOURCES = tst_qmutex.cpp
+win32:QT += core-private
diff --git a/tests/auto/corelib/thread/qmutex/tst_qmutex.cpp b/tests/auto/corelib/thread/qmutex/tst_qmutex.cpp
index 594bae674c..bf778e9fd1 100644
--- a/tests/auto/corelib/thread/qmutex/tst_qmutex.cpp
+++ b/tests/auto/corelib/thread/qmutex/tst_qmutex.cpp
@@ -31,16 +31,38 @@
#include <qatomic.h>
#include <qcoreapplication.h>
-#include <qdatetime.h>
+#include <qelapsedtimer.h>
#include <qmutex.h>
#include <qthread.h>
#include <qwaitcondition.h>
+#ifdef Q_OS_WIN
+#include <private/qsystemlibrary_p.h>
+#include <cmath>
+#endif
+
class tst_QMutex : public QObject
{
Q_OBJECT
+public:
+ enum class TimeUnit {
+ Nanoseconds,
+ Microseconds,
+ Milliseconds,
+ Seconds,
+ };
+ Q_ENUM(TimeUnit);
+
private slots:
- void tryLock();
+ void initTestCase();
+ void convertToMilliseconds_data();
+ void convertToMilliseconds();
+ void tryLock_non_recursive();
+ void try_lock_for_non_recursive();
+ void try_lock_until_non_recursive();
+ void tryLock_recursive();
+ void try_lock_for_recursive();
+ void try_lock_until_recursive();
void lock_unlock_locked_tryLock();
void stressTest();
void tryLockRace();
@@ -48,6 +70,8 @@ private slots:
void tryLockNegative_data();
void tryLockNegative();
void moreStress();
+private:
+ void initializeSystemTimersResolution();
};
static const int iterations = 100;
@@ -58,257 +82,922 @@ QSemaphore testsTurn;
QSemaphore threadsTurn;
enum { waitTime = 100 };
+uint systemTimersResolution = 1;
+
+#if QT_HAS_INCLUDE(<chrono>)
+static Q_CONSTEXPR std::chrono::milliseconds waitTimeAsDuration(waitTime);
+#endif
+
+/*
+ Depending on the OS, tryWaits may return early than expected because of the
+ resolution of the underlying timer is too coarse. E.g.: on Windows
+ WaitForSingleObjectEx does *not* use high resolution multimedia timers, and
+ it's actually very coarse, about 16msec by default.
+
+ Try to find out the timer resolution in here, so that the tryLock tests can
+ actually take into account early wakes.
+*/
+void tst_QMutex::initializeSystemTimersResolution()
+{
+#ifdef Q_OS_WIN
+ // according to MSDN, Windows can default up to this
+ systemTimersResolution = 16;
+
+ // private API. There's no way on Windows to otherwise know the
+ // actual resolution of the application's timers (you can only set it)
+ // cf. https://stackoverflow.com/questions/7685762/windows-7-timing-functions-how-to-use-getsystemtimeadjustment-correctly/11743614#11743614
+ typedef NTSTATUS (NTAPI *NtQueryTimerResolutionType)(OUT PULONG MinimumResolution,
+ OUT PULONG MaximumResolution,
+ OUT PULONG ActualResolution);
+
+ const NtQueryTimerResolutionType NtQueryTimerResolutionPtr =
+ reinterpret_cast<NtQueryTimerResolutionType>(QSystemLibrary::resolve(QStringLiteral("ntdll"), "NtQueryTimerResolution"));
+
+ if (!NtQueryTimerResolutionPtr)
+ return;
+
+ ULONG minimumResolution;
+ ULONG maximumResolution;
+ ULONG actualResolution;
+
+ if (!NtQueryTimerResolutionPtr(&minimumResolution, &maximumResolution, &actualResolution)) {
+ // the result is in 100ns units => adjust to msec
+ const double actualResolutionMsec = actualResolution / 10000.0;
+ systemTimersResolution = static_cast<int>(std::ceil(actualResolutionMsec));
+ }
+#endif // Q_OS_WIN
+}
+
+void tst_QMutex::initTestCase()
+{
+ initializeSystemTimersResolution();
+}
-void tst_QMutex::tryLock()
+void tst_QMutex::convertToMilliseconds_data()
{
- // test non-recursive mutex
+ QTest::addColumn<TimeUnit>("unit");
+ QTest::addColumn<double>("doubleValue");
+ QTest::addColumn<qint64>("intValue");
+ QTest::addColumn<qint64>("expected");
+
+
+ auto add = [](TimeUnit unit, double d, long long i, qint64 expected) {
+ const QScopedArrayPointer<char> enumName(QTest::toString(unit));
+ QTest::newRow(qPrintable(QString::asprintf("%s:%f:%lld", enumName.data(), d, i)))
+ << unit << d << qint64(i) << expected;
+ };
+
+ auto forAllUnitsAdd = [=](double d, long long i, qint64 expected) {
+ for (auto unit : {TimeUnit::Nanoseconds, TimeUnit::Microseconds, TimeUnit::Milliseconds, TimeUnit::Seconds})
+ add(unit, d, i, expected);
+ };
+
+ forAllUnitsAdd(-0.5, -1, 0); // all negative values result in 0
+
+ forAllUnitsAdd(0, 0, 0);
+
+ add(TimeUnit::Nanoseconds, 1, 1, 1);
+ add(TimeUnit::Nanoseconds, 1000 * 1000, 1000 * 1000, 1);
+ add(TimeUnit::Nanoseconds, 1000 * 1000 + 0.5, 1000 * 1000 + 1, 2);
+
+ add(TimeUnit::Microseconds, 1, 1, 1);
+ add(TimeUnit::Microseconds, 1000, 1000, 1);
+ add(TimeUnit::Microseconds, 1000 + 0.5, 1000 + 1, 2);
+
+ add(TimeUnit::Milliseconds, 1, 1, 1);
+ add(TimeUnit::Milliseconds, 1.5, 2, 2);
+
+ add(TimeUnit::Seconds, 0.9991, 1, 1000);
+
+ //
+ // overflowing int results in INT_MAX (equivalent to a spurious wakeup after ~24 days); check it:
+ //
+
+ // spot on:
+ add(TimeUnit::Nanoseconds, INT_MAX * 1000. * 1000, INT_MAX * Q_INT64_C(1000) * 1000, INT_MAX);
+ add(TimeUnit::Microseconds, INT_MAX * 1000., INT_MAX * Q_INT64_C(1000), INT_MAX);
+ add(TimeUnit::Milliseconds, INT_MAX, INT_MAX, INT_MAX);
+
+ // minimally above:
+ add(TimeUnit::Nanoseconds, INT_MAX * 1000. * 1000 + 1, INT_MAX * Q_INT64_C(1000) * 1000 + 1, INT_MAX);
+ add(TimeUnit::Microseconds, INT_MAX * 1000. + 1, INT_MAX * Q_INT64_C(1000) + 1, INT_MAX);
+ add(TimeUnit::Milliseconds, INT_MAX + 1., INT_MAX + Q_INT64_C(1), INT_MAX);
+ add(TimeUnit::Seconds, INT_MAX / 1000. + 1, INT_MAX / 1000 + 1, INT_MAX);
+
+ // minimally below:
+ add(TimeUnit::Nanoseconds, INT_MAX * 1000. * 1000 - 1, INT_MAX * Q_INT64_C(1000) * 1000 - 1, INT_MAX);
+ add(TimeUnit::Microseconds, INT_MAX * 1000. - 1, INT_MAX * Q_INT64_C(1000) - 1, INT_MAX);
+ add(TimeUnit::Milliseconds, INT_MAX - 0.1, INT_MAX , INT_MAX);
+
+}
+
+void tst_QMutex::convertToMilliseconds()
+{
+#if !QT_HAS_INCLUDE(<chrono>)
+ QSKIP("This test requires <chrono>");
+#else
+ QFETCH(TimeUnit, unit);
+ QFETCH(double, doubleValue);
+ QFETCH(qint64, intValue);
+ QFETCH(qint64, expected);
+
+ Q_CONSTEXPR qint64 maxShort = std::numeric_limits<short>::max();
+ Q_CONSTEXPR qint64 maxInt = std::numeric_limits<int>::max();
+ Q_CONSTEXPR qint64 maxUInt = std::numeric_limits<uint>::max();
+
+ switch (unit) {
+#define CASE(Unit, Period) \
+ case TimeUnit::Unit: \
+ DO(double, Period, doubleValue); \
+ if (intValue < maxShort) \
+ DO(short, Period, short(intValue)); \
+ if (intValue < maxInt) \
+ DO(int, Period, int(intValue)); \
+ DO(qint64, Period, intValue); \
+ if (intValue >= 0) { \
+ if (intValue < maxUInt) \
+ DO(uint, Period, uint(intValue)); \
+ DO(quint64, Period, quint64(intValue)); \
+ } \
+ break
+#define DO(Rep, Period, val) \
+ do { \
+ const std::chrono::duration<Rep, Period> wait((val)); \
+ QCOMPARE(QMutex::convertToMilliseconds(wait), expected); \
+ } while (0)
+
+ CASE(Nanoseconds, std::nano);
+ CASE(Microseconds, std::micro);
+ CASE(Milliseconds, std::milli);
+ CASE(Seconds, std::ratio<1>);
+#undef DO
+#undef CASE
+ }
+#endif
+}
+
+void tst_QMutex::tryLock_non_recursive()
+{
+ class Thread : public QThread
{
- class Thread : public QThread
+ public:
+ void run()
{
- public:
- void run()
- {
- testsTurn.release();
-
- // TEST 1: thread can't acquire lock
- threadsTurn.acquire();
- QVERIFY(!normalMutex.tryLock());
- testsTurn.release();
-
- // TEST 2: thread can acquire lock
- threadsTurn.acquire();
- QVERIFY(normalMutex.tryLock());
- QVERIFY(lockCount.testAndSetRelaxed(0, 1));
- QVERIFY(!normalMutex.tryLock());
- QVERIFY(lockCount.testAndSetRelaxed(1, 0));
- normalMutex.unlock();
- testsTurn.release();
-
- // TEST 3: thread can't acquire lock, timeout = waitTime
- threadsTurn.acquire();
- QTime timer;
- timer.start();
- QVERIFY(!normalMutex.tryLock(waitTime));
- QVERIFY(timer.elapsed() >= waitTime);
- testsTurn.release();
-
- // TEST 4: thread can acquire lock, timeout = waitTime
- threadsTurn.acquire();
- timer.start();
- QVERIFY(normalMutex.tryLock(waitTime));
- QVERIFY(timer.elapsed() <= waitTime);
- QVERIFY(lockCount.testAndSetRelaxed(0, 1));
- timer.start();
- // it's non-recursive, so the following lock needs to fail
- QVERIFY(!normalMutex.tryLock(waitTime));
- QVERIFY(timer.elapsed() >= waitTime);
- QVERIFY(lockCount.testAndSetRelaxed(1, 0));
- normalMutex.unlock();
- testsTurn.release();
-
- // TEST 5: thread can't acquire lock, timeout = 0
- threadsTurn.acquire();
- QVERIFY(!normalMutex.tryLock(0));
- testsTurn.release();
-
- // TEST 6: thread can acquire lock, timeout = 0
- threadsTurn.acquire();
- timer.start();
- QVERIFY(normalMutex.tryLock(0));
- QVERIFY(timer.elapsed() < waitTime);
- QVERIFY(lockCount.testAndSetRelaxed(0, 1));
- QVERIFY(!normalMutex.tryLock(0));
- QVERIFY(lockCount.testAndSetRelaxed(1, 0));
- normalMutex.unlock();
- testsTurn.release();
-
- // TEST 7 overflow: thread can acquire lock, timeout = 3000 (QTBUG-24795)
- threadsTurn.acquire();
- timer.start();
- QVERIFY(normalMutex.tryLock(3000));
- QVERIFY(timer.elapsed() < 3000);
- normalMutex.unlock();
- testsTurn.release();
-
- threadsTurn.acquire();
- }
- };
+ testsTurn.release();
+
+ // TEST 1: thread can't acquire lock
+ threadsTurn.acquire();
+ QVERIFY(!normalMutex.tryLock());
+ testsTurn.release();
+
+ // TEST 2: thread can acquire lock
+ threadsTurn.acquire();
+ QVERIFY(normalMutex.tryLock());
+ QVERIFY(lockCount.testAndSetRelaxed(0, 1));
+ QVERIFY(!normalMutex.tryLock());
+ QVERIFY(lockCount.testAndSetRelaxed(1, 0));
+ normalMutex.unlock();
+ testsTurn.release();
+
+ // TEST 3: thread can't acquire lock, timeout = waitTime
+ threadsTurn.acquire();
+ QElapsedTimer timer;
+ timer.start();
+ QVERIFY(!normalMutex.tryLock(waitTime));
+ QVERIFY(timer.elapsed() >= waitTime - systemTimersResolution);
+ testsTurn.release();
+
+ // TEST 4: thread can acquire lock, timeout = waitTime
+ threadsTurn.acquire();
+ timer.start();
+ QVERIFY(normalMutex.tryLock(waitTime));
+ QVERIFY(timer.elapsed() <= waitTime + systemTimersResolution);
+ QVERIFY(lockCount.testAndSetRelaxed(0, 1));
+ timer.start();
+ // it's non-recursive, so the following lock needs to fail
+ QVERIFY(!normalMutex.tryLock(waitTime));
+ QVERIFY(timer.elapsed() >= waitTime - systemTimersResolution);
+ QVERIFY(lockCount.testAndSetRelaxed(1, 0));
+ normalMutex.unlock();
+ testsTurn.release();
+
+ // TEST 5: thread can't acquire lock, timeout = 0
+ threadsTurn.acquire();
+ QVERIFY(!normalMutex.tryLock(0));
+ testsTurn.release();
+
+ // TEST 6: thread can acquire lock, timeout = 0
+ threadsTurn.acquire();
+ timer.start();
+ QVERIFY(normalMutex.tryLock(0));
+ QVERIFY(timer.elapsed() < waitTime + systemTimersResolution);
+ QVERIFY(lockCount.testAndSetRelaxed(0, 1));
+ QVERIFY(!normalMutex.tryLock(0));
+ QVERIFY(lockCount.testAndSetRelaxed(1, 0));
+ normalMutex.unlock();
+ testsTurn.release();
+
+ // TEST 7 overflow: thread can acquire lock, timeout = 3000 (QTBUG-24795)
+ threadsTurn.acquire();
+ timer.start();
+ QVERIFY(normalMutex.tryLock(3000));
+ QVERIFY(timer.elapsed() < 3000 + systemTimersResolution);
+ normalMutex.unlock();
+ testsTurn.release();
+
+ threadsTurn.acquire();
+ }
+ };
- Thread thread;
- thread.start();
+ Thread thread;
+ thread.start();
+
+ // TEST 1: thread can't acquire lock
+ testsTurn.acquire();
+ normalMutex.lock();
+ QVERIFY(lockCount.testAndSetRelaxed(0, 1));
+ threadsTurn.release();
+
+ // TEST 2: thread can acquire lock
+ testsTurn.acquire();
+ QVERIFY(lockCount.testAndSetRelaxed(1, 0));
+ normalMutex.unlock();
+ threadsTurn.release();
+
+ // TEST 3: thread can't acquire lock, timeout = waitTime
+ testsTurn.acquire();
+ normalMutex.lock();
+ QVERIFY(lockCount.testAndSetRelaxed(0, 1));
+ threadsTurn.release();
+
+ // TEST 4: thread can acquire lock, timeout = waitTime
+ testsTurn.acquire();
+ QVERIFY(lockCount.testAndSetRelaxed(1, 0));
+ normalMutex.unlock();
+ threadsTurn.release();
+
+ // TEST 5: thread can't acquire lock, timeout = 0
+ testsTurn.acquire();
+ normalMutex.lock();
+ QVERIFY(lockCount.testAndSetRelaxed(0, 1));
+ threadsTurn.release();
+
+ // TEST 6: thread can acquire lock, timeout = 0
+ testsTurn.acquire();
+ QVERIFY(lockCount.testAndSetRelaxed(1, 0));
+ normalMutex.unlock();
+ threadsTurn.release();
+
+ // TEST 7: thread can acquire lock, timeout = 3000 (QTBUG-24795)
+ testsTurn.acquire();
+ normalMutex.lock();
+ threadsTurn.release();
+ QThread::msleep(100);
+ normalMutex.unlock();
+
+ // wait for thread to finish
+ testsTurn.acquire();
+ threadsTurn.release();
+ thread.wait();
+}
- // TEST 1: thread can't acquire lock
- testsTurn.acquire();
- normalMutex.lock();
- QVERIFY(lockCount.testAndSetRelaxed(0, 1));
- threadsTurn.release();
-
- // TEST 2: thread can acquire lock
- testsTurn.acquire();
- QVERIFY(lockCount.testAndSetRelaxed(1, 0));
- normalMutex.unlock();
- threadsTurn.release();
-
- // TEST 3: thread can't acquire lock, timeout = waitTime
- testsTurn.acquire();
- normalMutex.lock();
- QVERIFY(lockCount.testAndSetRelaxed(0, 1));
- threadsTurn.release();
-
- // TEST 4: thread can acquire lock, timeout = waitTime
- testsTurn.acquire();
- QVERIFY(lockCount.testAndSetRelaxed(1, 0));
- normalMutex.unlock();
- threadsTurn.release();
-
- // TEST 5: thread can't acquire lock, timeout = 0
- testsTurn.acquire();
- normalMutex.lock();
- QVERIFY(lockCount.testAndSetRelaxed(0, 1));
- threadsTurn.release();
-
- // TEST 6: thread can acquire lock, timeout = 0
- testsTurn.acquire();
- QVERIFY(lockCount.testAndSetRelaxed(1, 0));
- normalMutex.unlock();
- threadsTurn.release();
-
- // TEST 7: thread can acquire lock, timeout = 3000 (QTBUG-24795)
- testsTurn.acquire();
- normalMutex.lock();
- threadsTurn.release();
- QThread::msleep(100);
- normalMutex.unlock();
-
- // wait for thread to finish
- testsTurn.acquire();
- threadsTurn.release();
- thread.wait();
- }
+void tst_QMutex::try_lock_for_non_recursive() {
+#if !QT_HAS_INCLUDE(<chrono>)
+ QSKIP("This test requires <chrono>");
+#else
+ class Thread : public QThread
+ {
+ public:
+ void run()
+ {
+ testsTurn.release();
+
+ // TEST 1: thread can't acquire lock
+ threadsTurn.acquire();
+ QVERIFY(!normalMutex.try_lock());
+ testsTurn.release();
+
+ // TEST 2: thread can acquire lock
+ threadsTurn.acquire();
+ QVERIFY(normalMutex.try_lock());
+ QVERIFY(lockCount.testAndSetRelaxed(0, 1));
+ QVERIFY(!normalMutex.try_lock());
+ QVERIFY(lockCount.testAndSetRelaxed(1, 0));
+ normalMutex.unlock();
+ testsTurn.release();
+
+ // TEST 3: thread can't acquire lock, timeout = waitTime
+ threadsTurn.acquire();
+ QElapsedTimer timer;
+ timer.start();
+ QVERIFY(!normalMutex.try_lock_for(waitTimeAsDuration));
+ QVERIFY(timer.elapsed() >= waitTime - systemTimersResolution);
+ testsTurn.release();
+
+ // TEST 4: thread can acquire lock, timeout = waitTime
+ threadsTurn.acquire();
+ timer.start();
+ QVERIFY(normalMutex.try_lock_for(waitTimeAsDuration));
+ QVERIFY(timer.elapsed() <= waitTime + systemTimersResolution);
+ QVERIFY(lockCount.testAndSetRelaxed(0, 1));
+ timer.start();
+ // it's non-recursive, so the following lock needs to fail
+ QVERIFY(!normalMutex.try_lock_for(waitTimeAsDuration));
+ QVERIFY(timer.elapsed() >= waitTime - systemTimersResolution);
+ QVERIFY(lockCount.testAndSetRelaxed(1, 0));
+ normalMutex.unlock();
+ testsTurn.release();
+
+ // TEST 5: thread can't acquire lock, timeout = 0
+ threadsTurn.acquire();
+ QVERIFY(!normalMutex.try_lock_for(std::chrono::milliseconds::zero()));
+ testsTurn.release();
+
+ // TEST 6: thread can acquire lock, timeout = 0
+ threadsTurn.acquire();
+ timer.start();
+ QVERIFY(normalMutex.try_lock_for(std::chrono::milliseconds::zero()));
+ QVERIFY(timer.elapsed() < waitTime + systemTimersResolution);
+ QVERIFY(lockCount.testAndSetRelaxed(0, 1));
+ QVERIFY(!normalMutex.try_lock_for(std::chrono::milliseconds::zero()));
+ QVERIFY(lockCount.testAndSetRelaxed(1, 0));
+ normalMutex.unlock();
+ testsTurn.release();
+
+ // TEST 7 overflow: thread can acquire lock, timeout = 3000 (QTBUG-24795)
+ threadsTurn.acquire();
+ timer.start();
+ QVERIFY(normalMutex.try_lock_for(std::chrono::milliseconds(3000)));
+ QVERIFY(timer.elapsed() < 3000 + systemTimersResolution);
+ normalMutex.unlock();
+ testsTurn.release();
+
+ threadsTurn.acquire();
+ }
+ };
+
+ Thread thread;
+ thread.start();
+
+ // TEST 1: thread can't acquire lock
+ testsTurn.acquire();
+ normalMutex.lock();
+ QVERIFY(lockCount.testAndSetRelaxed(0, 1));
+ threadsTurn.release();
+
+ // TEST 2: thread can acquire lock
+ testsTurn.acquire();
+ QVERIFY(lockCount.testAndSetRelaxed(1, 0));
+ normalMutex.unlock();
+ threadsTurn.release();
+
+ // TEST 3: thread can't acquire lock, timeout = waitTime
+ testsTurn.acquire();
+ normalMutex.lock();
+ QVERIFY(lockCount.testAndSetRelaxed(0, 1));
+ threadsTurn.release();
+
+ // TEST 4: thread can acquire lock, timeout = waitTime
+ testsTurn.acquire();
+ QVERIFY(lockCount.testAndSetRelaxed(1, 0));
+ normalMutex.unlock();
+ threadsTurn.release();
+
+ // TEST 5: thread can't acquire lock, timeout = 0
+ testsTurn.acquire();
+ normalMutex.lock();
+ QVERIFY(lockCount.testAndSetRelaxed(0, 1));
+ threadsTurn.release();
+
+ // TEST 6: thread can acquire lock, timeout = 0
+ testsTurn.acquire();
+ QVERIFY(lockCount.testAndSetRelaxed(1, 0));
+ normalMutex.unlock();
+ threadsTurn.release();
+
+ // TEST 7: thread can acquire lock, timeout = 3000 (QTBUG-24795)
+ testsTurn.acquire();
+ normalMutex.lock();
+ threadsTurn.release();
+ QThread::msleep(100);
+ normalMutex.unlock();
+
+ // wait for thread to finish
+ testsTurn.acquire();
+ threadsTurn.release();
+ thread.wait();
+#endif
+}
- // test recursive mutex
+void tst_QMutex::try_lock_until_non_recursive()
+{
+#if !QT_HAS_INCLUDE(<chrono>)
+ QSKIP("This test requires <chrono>");
+#else
+ class Thread : public QThread
{
- class Thread : public QThread
+ public:
+ void run()
{
- public:
- void run()
- {
- testsTurn.release();
-
- threadsTurn.acquire();
- QVERIFY(!recursiveMutex.tryLock());
- testsTurn.release();
-
- threadsTurn.acquire();
- QVERIFY(recursiveMutex.tryLock());
- QVERIFY(lockCount.testAndSetRelaxed(0, 1));
- QVERIFY(recursiveMutex.tryLock());
- QVERIFY(lockCount.testAndSetRelaxed(1, 2));
- QVERIFY(lockCount.testAndSetRelaxed(2, 1));
- recursiveMutex.unlock();
- QVERIFY(lockCount.testAndSetRelaxed(1, 0));
- recursiveMutex.unlock();
- testsTurn.release();
-
- threadsTurn.acquire();
- QTime timer;
- timer.start();
- QVERIFY(!recursiveMutex.tryLock(waitTime));
- QVERIFY(timer.elapsed() >= waitTime);
- QVERIFY(!recursiveMutex.tryLock(0));
- testsTurn.release();
-
- threadsTurn.acquire();
- timer.start();
- QVERIFY(recursiveMutex.tryLock(waitTime));
- QVERIFY(timer.elapsed() <= waitTime);
- QVERIFY(lockCount.testAndSetRelaxed(0, 1));
- QVERIFY(recursiveMutex.tryLock(waitTime));
- QVERIFY(lockCount.testAndSetRelaxed(1, 2));
- QVERIFY(lockCount.testAndSetRelaxed(2, 1));
- recursiveMutex.unlock();
- QVERIFY(lockCount.testAndSetRelaxed(1, 0));
- recursiveMutex.unlock();
- testsTurn.release();
-
- threadsTurn.acquire();
- QVERIFY(!recursiveMutex.tryLock(0));
- QVERIFY(!recursiveMutex.tryLock(0));
- testsTurn.release();
-
- threadsTurn.acquire();
- timer.start();
- QVERIFY(recursiveMutex.tryLock(0));
- QVERIFY(timer.elapsed() < waitTime);
- QVERIFY(lockCount.testAndSetRelaxed(0, 1));
- QVERIFY(recursiveMutex.tryLock(0));
- QVERIFY(lockCount.testAndSetRelaxed(1, 2));
- QVERIFY(lockCount.testAndSetRelaxed(2, 1));
- recursiveMutex.unlock();
- QVERIFY(lockCount.testAndSetRelaxed(1, 0));
- recursiveMutex.unlock();
- testsTurn.release();
-
- threadsTurn.acquire();
- }
- };
+ const std::chrono::milliseconds systemTimersResolutionAsDuration(systemTimersResolution);
+ testsTurn.release();
+
+ // TEST 1: thread can't acquire lock
+ threadsTurn.acquire();
+ QVERIFY(!normalMutex.try_lock());
+ testsTurn.release();
+
+ // TEST 2: thread can acquire lock
+ threadsTurn.acquire();
+ QVERIFY(normalMutex.try_lock());
+ QVERIFY(lockCount.testAndSetRelaxed(0, 1));
+ QVERIFY(!normalMutex.try_lock());
+ QVERIFY(lockCount.testAndSetRelaxed(1, 0));
+ normalMutex.unlock();
+ testsTurn.release();
+
+ // TEST 3: thread can't acquire lock, timeout = waitTime
+ threadsTurn.acquire();
+ auto endTimePoint = std::chrono::steady_clock::now() + waitTimeAsDuration;
+ QVERIFY(!normalMutex.try_lock_until(endTimePoint));
+ QVERIFY(std::chrono::steady_clock::now() >= endTimePoint - systemTimersResolutionAsDuration);
+ testsTurn.release();
+
+ // TEST 4: thread can acquire lock, timeout = waitTime
+ threadsTurn.acquire();
+ endTimePoint = std::chrono::steady_clock::now() + waitTimeAsDuration;
+ QVERIFY(normalMutex.try_lock_until(endTimePoint));
+ QVERIFY(std::chrono::steady_clock::now() <= endTimePoint + systemTimersResolutionAsDuration);
+ QVERIFY(lockCount.testAndSetRelaxed(0, 1));
+ endTimePoint = std::chrono::steady_clock::now() + waitTimeAsDuration;
+ // it's non-recursive, so the following lock needs to fail
+ QVERIFY(!normalMutex.try_lock_until(endTimePoint));
+ QVERIFY(std::chrono::steady_clock::now() >= endTimePoint - systemTimersResolutionAsDuration);
+ QVERIFY(lockCount.testAndSetRelaxed(1, 0));
+ normalMutex.unlock();
+ testsTurn.release();
+
+ // TEST 5: thread can't acquire lock, timeout = 0
+ threadsTurn.acquire();
+ QVERIFY(!normalMutex.try_lock_until(std::chrono::steady_clock::now()));
+ testsTurn.release();
+
+ // TEST 6: thread can acquire lock, timeout = 0
+ threadsTurn.acquire();
+ endTimePoint = std::chrono::steady_clock::now() + waitTimeAsDuration;
+ QVERIFY(normalMutex.try_lock_until(std::chrono::steady_clock::now()));
+ QVERIFY(std::chrono::steady_clock::now() < endTimePoint + systemTimersResolutionAsDuration);
+ QVERIFY(lockCount.testAndSetRelaxed(0, 1));
+ QVERIFY(!normalMutex.try_lock_until(std::chrono::steady_clock::now()));
+ QVERIFY(lockCount.testAndSetRelaxed(1, 0));
+ normalMutex.unlock();
+ testsTurn.release();
+
+ // TEST 7 overflow: thread can acquire lock, timeout = 3000 (QTBUG-24795)
+ threadsTurn.acquire();
+ endTimePoint = std::chrono::steady_clock::now() + std::chrono::milliseconds(3000);
+ QVERIFY(normalMutex.try_lock_until(endTimePoint));
+ QVERIFY(std::chrono::steady_clock::now() < endTimePoint + systemTimersResolutionAsDuration);
+ normalMutex.unlock();
+ testsTurn.release();
+
+ threadsTurn.acquire();
+ }
+ };
- Thread thread;
- thread.start();
+ Thread thread;
+ thread.start();
+
+ // TEST 1: thread can't acquire lock
+ testsTurn.acquire();
+ normalMutex.lock();
+ QVERIFY(lockCount.testAndSetRelaxed(0, 1));
+ threadsTurn.release();
+
+ // TEST 2: thread can acquire lock
+ testsTurn.acquire();
+ QVERIFY(lockCount.testAndSetRelaxed(1, 0));
+ normalMutex.unlock();
+ threadsTurn.release();
+
+ // TEST 3: thread can't acquire lock, timeout = waitTime
+ testsTurn.acquire();
+ normalMutex.lock();
+ QVERIFY(lockCount.testAndSetRelaxed(0, 1));
+ threadsTurn.release();
+
+ // TEST 4: thread can acquire lock, timeout = waitTime
+ testsTurn.acquire();
+ QVERIFY(lockCount.testAndSetRelaxed(1, 0));
+ normalMutex.unlock();
+ threadsTurn.release();
+
+ // TEST 5: thread can't acquire lock, timeout = 0
+ testsTurn.acquire();
+ normalMutex.lock();
+ QVERIFY(lockCount.testAndSetRelaxed(0, 1));
+ threadsTurn.release();
+
+ // TEST 6: thread can acquire lock, timeout = 0
+ testsTurn.acquire();
+ QVERIFY(lockCount.testAndSetRelaxed(1, 0));
+ normalMutex.unlock();
+ threadsTurn.release();
+
+ // TEST 7: thread can acquire lock, timeout = 3000 (QTBUG-24795)
+ testsTurn.acquire();
+ normalMutex.lock();
+ threadsTurn.release();
+ QThread::msleep(100);
+ normalMutex.unlock();
+
+ // wait for thread to finish
+ testsTurn.acquire();
+ threadsTurn.release();
+ thread.wait();
+#endif
+}
- // thread can't acquire lock
- testsTurn.acquire();
- recursiveMutex.lock();
- QVERIFY(lockCount.testAndSetRelaxed(0, 1));
- recursiveMutex.lock();
- QVERIFY(lockCount.testAndSetRelaxed(1, 2));
- threadsTurn.release();
-
- // thread can acquire lock
- testsTurn.acquire();
- QVERIFY(lockCount.testAndSetRelaxed(2, 1));
- recursiveMutex.unlock();
- QVERIFY(lockCount.testAndSetRelaxed(1, 0));
- recursiveMutex.unlock();
- threadsTurn.release();
-
- // thread can't acquire lock, timeout = waitTime
- testsTurn.acquire();
- recursiveMutex.lock();
- QVERIFY(lockCount.testAndSetRelaxed(0, 1));
- recursiveMutex.lock();
- QVERIFY(lockCount.testAndSetRelaxed(1, 2));
- threadsTurn.release();
-
- // thread can acquire lock, timeout = waitTime
- testsTurn.acquire();
- QVERIFY(lockCount.testAndSetRelaxed(2, 1));
- recursiveMutex.unlock();
- QVERIFY(lockCount.testAndSetRelaxed(1, 0));
- recursiveMutex.unlock();
- threadsTurn.release();
-
- // thread can't acquire lock, timeout = 0
- testsTurn.acquire();
- recursiveMutex.lock();
- QVERIFY(lockCount.testAndSetRelaxed(0, 1));
- recursiveMutex.lock();
- QVERIFY(lockCount.testAndSetRelaxed(1, 2));
- threadsTurn.release();
-
- // thread can acquire lock, timeout = 0
- testsTurn.acquire();
- QVERIFY(lockCount.testAndSetRelaxed(2, 1));
- recursiveMutex.unlock();
- QVERIFY(lockCount.testAndSetRelaxed(1, 0));
- recursiveMutex.unlock();
- threadsTurn.release();
-
- // stop thread
- testsTurn.acquire();
- threadsTurn.release();
- thread.wait();
- }
+void tst_QMutex::tryLock_recursive()
+{
+ class Thread : public QThread
+ {
+ public:
+ void run()
+ {
+ testsTurn.release();
+
+ threadsTurn.acquire();
+ QVERIFY(!recursiveMutex.tryLock());
+ testsTurn.release();
+
+ threadsTurn.acquire();
+ QVERIFY(recursiveMutex.tryLock());
+ QVERIFY(lockCount.testAndSetRelaxed(0, 1));
+ QVERIFY(recursiveMutex.tryLock());
+ QVERIFY(lockCount.testAndSetRelaxed(1, 2));
+ QVERIFY(lockCount.testAndSetRelaxed(2, 1));
+ recursiveMutex.unlock();
+ QVERIFY(lockCount.testAndSetRelaxed(1, 0));
+ recursiveMutex.unlock();
+ testsTurn.release();
+
+ threadsTurn.acquire();
+ QElapsedTimer timer;
+ timer.start();
+ QVERIFY(!recursiveMutex.tryLock(waitTime));
+ QVERIFY(timer.elapsed() >= waitTime - systemTimersResolution);
+ QVERIFY(!recursiveMutex.tryLock(0));
+ testsTurn.release();
+
+ threadsTurn.acquire();
+ timer.start();
+ QVERIFY(recursiveMutex.tryLock(waitTime));
+ QVERIFY(timer.elapsed() <= waitTime + systemTimersResolution);
+ QVERIFY(lockCount.testAndSetRelaxed(0, 1));
+ QVERIFY(recursiveMutex.tryLock(waitTime));
+ QVERIFY(lockCount.testAndSetRelaxed(1, 2));
+ QVERIFY(lockCount.testAndSetRelaxed(2, 1));
+ recursiveMutex.unlock();
+ QVERIFY(lockCount.testAndSetRelaxed(1, 0));
+ recursiveMutex.unlock();
+ testsTurn.release();
+
+ threadsTurn.acquire();
+ QVERIFY(!recursiveMutex.tryLock(0));
+ QVERIFY(!recursiveMutex.tryLock(0));
+ testsTurn.release();
+
+ threadsTurn.acquire();
+ timer.start();
+ QVERIFY(recursiveMutex.tryLock(0));
+ QVERIFY(timer.elapsed() < waitTime + systemTimersResolution);
+ QVERIFY(lockCount.testAndSetRelaxed(0, 1));
+ QVERIFY(recursiveMutex.tryLock(0));
+ QVERIFY(lockCount.testAndSetRelaxed(1, 2));
+ QVERIFY(lockCount.testAndSetRelaxed(2, 1));
+ recursiveMutex.unlock();
+ QVERIFY(lockCount.testAndSetRelaxed(1, 0));
+ recursiveMutex.unlock();
+ testsTurn.release();
+
+ threadsTurn.acquire();
+ }
+ };
+
+ Thread thread;
+ thread.start();
+
+ // thread can't acquire lock
+ testsTurn.acquire();
+ recursiveMutex.lock();
+ QVERIFY(lockCount.testAndSetRelaxed(0, 1));
+ recursiveMutex.lock();
+ QVERIFY(lockCount.testAndSetRelaxed(1, 2));
+ threadsTurn.release();
+
+ // thread can acquire lock
+ testsTurn.acquire();
+ QVERIFY(lockCount.testAndSetRelaxed(2, 1));
+ recursiveMutex.unlock();
+ QVERIFY(lockCount.testAndSetRelaxed(1, 0));
+ recursiveMutex.unlock();
+ threadsTurn.release();
+
+ // thread can't acquire lock, timeout = waitTime
+ testsTurn.acquire();
+ recursiveMutex.lock();
+ QVERIFY(lockCount.testAndSetRelaxed(0, 1));
+ recursiveMutex.lock();
+ QVERIFY(lockCount.testAndSetRelaxed(1, 2));
+ threadsTurn.release();
+
+ // thread can acquire lock, timeout = waitTime
+ testsTurn.acquire();
+ QVERIFY(lockCount.testAndSetRelaxed(2, 1));
+ recursiveMutex.unlock();
+ QVERIFY(lockCount.testAndSetRelaxed(1, 0));
+ recursiveMutex.unlock();
+ threadsTurn.release();
+
+ // thread can't acquire lock, timeout = 0
+ testsTurn.acquire();
+ recursiveMutex.lock();
+ QVERIFY(lockCount.testAndSetRelaxed(0, 1));
+ recursiveMutex.lock();
+ QVERIFY(lockCount.testAndSetRelaxed(1, 2));
+ threadsTurn.release();
+
+ // thread can acquire lock, timeout = 0
+ testsTurn.acquire();
+ QVERIFY(lockCount.testAndSetRelaxed(2, 1));
+ recursiveMutex.unlock();
+ QVERIFY(lockCount.testAndSetRelaxed(1, 0));
+ recursiveMutex.unlock();
+ threadsTurn.release();
+
+ // stop thread
+ testsTurn.acquire();
+ threadsTurn.release();
+ thread.wait();
+}
+
+void tst_QMutex::try_lock_for_recursive()
+{
+#if !QT_HAS_INCLUDE(<chrono>)
+ QSKIP("This test requires <chrono>");
+#else
+ class Thread : public QThread
+ {
+ public:
+ void run()
+ {
+ const std::chrono::milliseconds systemTimersResolutionAsDuration(systemTimersResolution);
+ testsTurn.release();
+
+ threadsTurn.acquire();
+ QVERIFY(!recursiveMutex.try_lock());
+ testsTurn.release();
+
+ threadsTurn.acquire();
+ QVERIFY(recursiveMutex.try_lock());
+ QVERIFY(lockCount.testAndSetRelaxed(0, 1));
+ QVERIFY(recursiveMutex.try_lock());
+ QVERIFY(lockCount.testAndSetRelaxed(1, 2));
+ QVERIFY(lockCount.testAndSetRelaxed(2, 1));
+ recursiveMutex.unlock();
+ QVERIFY(lockCount.testAndSetRelaxed(1, 0));
+ recursiveMutex.unlock();
+ testsTurn.release();
+
+ threadsTurn.acquire();
+ QElapsedTimer timer;
+ timer.start();
+ QVERIFY(!recursiveMutex.try_lock_for(waitTimeAsDuration));
+ QVERIFY(timer.elapsed() >= waitTime - systemTimersResolution);
+ QVERIFY(!recursiveMutex.try_lock_for(std::chrono::milliseconds::zero()));
+ testsTurn.release();
+
+ threadsTurn.acquire();
+ timer.start();
+ QVERIFY(recursiveMutex.try_lock_for(waitTimeAsDuration));
+ QVERIFY(timer.elapsed() <= waitTime + systemTimersResolution);
+ QVERIFY(lockCount.testAndSetRelaxed(0, 1));
+ QVERIFY(recursiveMutex.try_lock_for(waitTimeAsDuration));
+ QVERIFY(lockCount.testAndSetRelaxed(1, 2));
+ QVERIFY(lockCount.testAndSetRelaxed(2, 1));
+ recursiveMutex.unlock();
+ QVERIFY(lockCount.testAndSetRelaxed(1, 0));
+ recursiveMutex.unlock();
+ testsTurn.release();
+
+ threadsTurn.acquire();
+ QVERIFY(!recursiveMutex.try_lock_for(std::chrono::milliseconds::zero()));
+ QVERIFY(!recursiveMutex.try_lock_for(std::chrono::milliseconds::zero()));
+ testsTurn.release();
+
+ threadsTurn.acquire();
+ timer.start();
+ QVERIFY(recursiveMutex.try_lock_for(std::chrono::milliseconds::zero()));
+ QVERIFY(timer.elapsed() < waitTime + systemTimersResolution);
+ QVERIFY(lockCount.testAndSetRelaxed(0, 1));
+ QVERIFY(recursiveMutex.try_lock_for(std::chrono::milliseconds::zero()));
+ QVERIFY(lockCount.testAndSetRelaxed(1, 2));
+ QVERIFY(lockCount.testAndSetRelaxed(2, 1));
+ recursiveMutex.unlock();
+ QVERIFY(lockCount.testAndSetRelaxed(1, 0));
+ recursiveMutex.unlock();
+ testsTurn.release();
+
+ threadsTurn.acquire();
+ }
+ };
+
+ Thread thread;
+ thread.start();
+
+ // thread can't acquire lock
+ testsTurn.acquire();
+ recursiveMutex.lock();
+ QVERIFY(lockCount.testAndSetRelaxed(0, 1));
+ recursiveMutex.lock();
+ QVERIFY(lockCount.testAndSetRelaxed(1, 2));
+ threadsTurn.release();
+
+ // thread can acquire lock
+ testsTurn.acquire();
+ QVERIFY(lockCount.testAndSetRelaxed(2, 1));
+ recursiveMutex.unlock();
+ QVERIFY(lockCount.testAndSetRelaxed(1, 0));
+ recursiveMutex.unlock();
+ threadsTurn.release();
+
+ // thread can't acquire lock, timeout = waitTime
+ testsTurn.acquire();
+ recursiveMutex.lock();
+ QVERIFY(lockCount.testAndSetRelaxed(0, 1));
+ recursiveMutex.lock();
+ QVERIFY(lockCount.testAndSetRelaxed(1, 2));
+ threadsTurn.release();
+
+ // thread can acquire lock, timeout = waitTime
+ testsTurn.acquire();
+ QVERIFY(lockCount.testAndSetRelaxed(2, 1));
+ recursiveMutex.unlock();
+ QVERIFY(lockCount.testAndSetRelaxed(1, 0));
+ recursiveMutex.unlock();
+ threadsTurn.release();
+
+ // thread can't acquire lock, timeout = 0
+ testsTurn.acquire();
+ recursiveMutex.lock();
+ QVERIFY(lockCount.testAndSetRelaxed(0, 1));
+ recursiveMutex.lock();
+ QVERIFY(lockCount.testAndSetRelaxed(1, 2));
+ threadsTurn.release();
+
+ // thread can acquire lock, timeout = 0
+ testsTurn.acquire();
+ QVERIFY(lockCount.testAndSetRelaxed(2, 1));
+ recursiveMutex.unlock();
+ QVERIFY(lockCount.testAndSetRelaxed(1, 0));
+ recursiveMutex.unlock();
+ threadsTurn.release();
+
+ // stop thread
+ testsTurn.acquire();
+ threadsTurn.release();
+ thread.wait();
+#endif
+}
+
+void tst_QMutex::try_lock_until_recursive()
+{
+#if !QT_HAS_INCLUDE(<chrono>)
+ QSKIP("This test requires <chrono>");
+#else
+ class Thread : public QThread
+ {
+ public:
+ void run()
+ {
+ const std::chrono::milliseconds systemTimersResolutionAsDuration(systemTimersResolution);
+ testsTurn.release();
+
+ threadsTurn.acquire();
+ QVERIFY(!recursiveMutex.try_lock());
+ testsTurn.release();
+
+ threadsTurn.acquire();
+ QVERIFY(recursiveMutex.try_lock());
+ QVERIFY(lockCount.testAndSetRelaxed(0, 1));
+ QVERIFY(recursiveMutex.try_lock());
+ QVERIFY(lockCount.testAndSetRelaxed(1, 2));
+ QVERIFY(lockCount.testAndSetRelaxed(2, 1));
+ recursiveMutex.unlock();
+ QVERIFY(lockCount.testAndSetRelaxed(1, 0));
+ recursiveMutex.unlock();
+ testsTurn.release();
+
+ threadsTurn.acquire();
+ auto endTimePoint = std::chrono::steady_clock::now() + waitTimeAsDuration;
+ QVERIFY(!recursiveMutex.try_lock_until(endTimePoint));
+ QVERIFY(std::chrono::steady_clock::now() >= endTimePoint - systemTimersResolutionAsDuration);
+ QVERIFY(!recursiveMutex.try_lock());
+ testsTurn.release();
+
+ threadsTurn.acquire();
+ endTimePoint = std::chrono::steady_clock::now() + waitTimeAsDuration;
+ QVERIFY(recursiveMutex.try_lock_until(endTimePoint));
+ QVERIFY(std::chrono::steady_clock::now() <= endTimePoint + systemTimersResolutionAsDuration);
+ QVERIFY(lockCount.testAndSetRelaxed(0, 1));
+ endTimePoint = std::chrono::steady_clock::now() + waitTimeAsDuration;
+ QVERIFY(recursiveMutex.try_lock_until(endTimePoint));
+ QVERIFY(lockCount.testAndSetRelaxed(1, 2));
+ QVERIFY(lockCount.testAndSetRelaxed(2, 1));
+ recursiveMutex.unlock();
+ QVERIFY(lockCount.testAndSetRelaxed(1, 0));
+ recursiveMutex.unlock();
+ testsTurn.release();
+
+ threadsTurn.acquire();
+ QVERIFY(!recursiveMutex.try_lock_until(std::chrono::steady_clock::now()));
+ QVERIFY(!recursiveMutex.try_lock_until(std::chrono::steady_clock::now()));
+ testsTurn.release();
+
+ threadsTurn.acquire();
+ endTimePoint = std::chrono::steady_clock::now() + waitTimeAsDuration;
+ QVERIFY(recursiveMutex.try_lock_until(std::chrono::steady_clock::now()));
+ QVERIFY(std::chrono::steady_clock::now() <= endTimePoint + systemTimersResolutionAsDuration);
+ QVERIFY(lockCount.testAndSetRelaxed(0, 1));
+ QVERIFY(recursiveMutex.try_lock_until(std::chrono::steady_clock::now()));
+ QVERIFY(lockCount.testAndSetRelaxed(1, 2));
+ QVERIFY(lockCount.testAndSetRelaxed(2, 1));
+ recursiveMutex.unlock();
+ QVERIFY(lockCount.testAndSetRelaxed(1, 0));
+ recursiveMutex.unlock();
+ testsTurn.release();
+
+ threadsTurn.acquire();
+ }
+ };
+
+ Thread thread;
+ thread.start();
+
+ // thread can't acquire lock
+ testsTurn.acquire();
+ recursiveMutex.lock();
+ QVERIFY(lockCount.testAndSetRelaxed(0, 1));
+ recursiveMutex.lock();
+ QVERIFY(lockCount.testAndSetRelaxed(1, 2));
+ threadsTurn.release();
+
+ // thread can acquire lock
+ testsTurn.acquire();
+ QVERIFY(lockCount.testAndSetRelaxed(2, 1));
+ recursiveMutex.unlock();
+ QVERIFY(lockCount.testAndSetRelaxed(1, 0));
+ recursiveMutex.unlock();
+ threadsTurn.release();
+
+ // thread can't acquire lock, timeout = waitTime
+ testsTurn.acquire();
+ recursiveMutex.lock();
+ QVERIFY(lockCount.testAndSetRelaxed(0, 1));
+ recursiveMutex.lock();
+ QVERIFY(lockCount.testAndSetRelaxed(1, 2));
+ threadsTurn.release();
+
+ // thread can acquire lock, timeout = waitTime
+ testsTurn.acquire();
+ QVERIFY(lockCount.testAndSetRelaxed(2, 1));
+ recursiveMutex.unlock();
+ QVERIFY(lockCount.testAndSetRelaxed(1, 0));
+ recursiveMutex.unlock();
+ threadsTurn.release();
+
+ // thread can't acquire lock, timeout = 0
+ testsTurn.acquire();
+ recursiveMutex.lock();
+ QVERIFY(lockCount.testAndSetRelaxed(0, 1));
+ recursiveMutex.lock();
+ QVERIFY(lockCount.testAndSetRelaxed(1, 2));
+ threadsTurn.release();
+
+ // thread can acquire lock, timeout = 0
+ testsTurn.acquire();
+ QVERIFY(lockCount.testAndSetRelaxed(2, 1));
+ recursiveMutex.unlock();
+ QVERIFY(lockCount.testAndSetRelaxed(1, 0));
+ recursiveMutex.unlock();
+ threadsTurn.release();
+
+ // stop thread
+ testsTurn.acquire();
+ threadsTurn.release();
+ thread.wait();
+#endif
}
class mutex_Thread : public QThread
@@ -439,7 +1128,7 @@ enum { one_minute = 6 * 1000, //not really one minute, but else it is too long.
class StressTestThread : public QThread
{
- QTime t;
+ QElapsedTimer t;
public:
static QBasicAtomicInt lockCount;
static QBasicAtomicInt sentinel;
@@ -491,7 +1180,7 @@ public:
void run()
{
- QTime t;
+ QElapsedTimer t;
t.start();
do {
if (mutex.tryLock())
@@ -619,7 +1308,7 @@ void tst_QMutex::tryLockNegative()
class MoreStressTestThread : public QThread
{
- QTime t;
+ QElapsedTimer t;
public:
static QAtomicInt lockCount;
static QAtomicInt sentinel[threadCount];
diff --git a/tests/auto/corelib/thread/qsemaphore/tst_qsemaphore.cpp b/tests/auto/corelib/thread/qsemaphore/tst_qsemaphore.cpp
index 341bd21e5a..8597bf1a6d 100644
--- a/tests/auto/corelib/thread/qsemaphore/tst_qsemaphore.cpp
+++ b/tests/auto/corelib/thread/qsemaphore/tst_qsemaphore.cpp
@@ -350,15 +350,9 @@ const int AlphabetSize = sizeof(alphabet) - 1;
const int BufferSize = 4096; // GCD of BufferSize and alphabet size must be 1
char buffer[BufferSize];
-#ifndef Q_OS_WINCE
const int ProducerChunkSize = 3;
const int ConsumerChunkSize = 7;
const int Multiplier = 10;
-#else
-const int ProducerChunkSize = 2;
-const int ConsumerChunkSize = 5;
-const int Multiplier = 3;
-#endif
// note: the code depends on the fact that DataSize is a multiple of
// ProducerChunkSize, ConsumerChunkSize, and BufferSize
diff --git a/tests/auto/corelib/thread/qthread/tst_qthread.cpp b/tests/auto/corelib/thread/qthread/tst_qthread.cpp
index bbd319d2db..0efbc5d01e 100644
--- a/tests/auto/corelib/thread/qthread/tst_qthread.cpp
+++ b/tests/auto/corelib/thread/qthread/tst_qthread.cpp
@@ -95,9 +95,7 @@ private slots:
void requestTermination();
-#ifndef Q_OS_WINCE
void stressTest();
-#endif
void quitLock();
};
@@ -664,7 +662,7 @@ void NativeThreadWrapper::start(FunctionPointer functionPointer, void *data)
#if defined Q_OS_UNIX
const int state = pthread_create(&nativeThreadHandle, 0, NativeThreadWrapper::runUnix, this);
Q_UNUSED(state);
-#elif defined(Q_OS_WINCE) || defined(Q_OS_WINRT)
+#elif defined(Q_OS_WINRT)
nativeThreadHandle = CreateThread(NULL, 0 , (LPTHREAD_START_ROUTINE)NativeThreadWrapper::runWin , this, 0, NULL);
#elif defined Q_OS_WIN
unsigned thrdid = 0;
@@ -684,11 +682,7 @@ void NativeThreadWrapper::join()
#if defined Q_OS_UNIX
pthread_join(nativeThreadHandle, 0);
#elif defined Q_OS_WIN
-#ifndef Q_OS_WINCE
WaitForSingleObjectEx(nativeThreadHandle, INFINITE, FALSE);
-#else
- WaitForSingleObject(nativeThreadHandle, INFINITE);
-#endif
CloseHandle(nativeThreadHandle);
#endif
}
@@ -874,13 +868,8 @@ void tst_QThread::adoptedThreadExecFinished()
void tst_QThread::adoptMultipleThreads()
{
#if defined(Q_OS_WIN)
- // Windows CE is not capable of handling that many threads. On the emulator it is dead with 26 threads already.
-# if defined(Q_OS_WINCE)
- const int numThreads = 20;
-# else
// need to test lots of threads, so that we exceed MAXIMUM_WAIT_OBJECTS in qt_adopted_thread_watcher()
const int numThreads = 200;
-# endif
#else
const int numThreads = 5;
#endif
@@ -911,13 +900,8 @@ void tst_QThread::adoptMultipleThreads()
void tst_QThread::adoptMultipleThreadsOverlap()
{
#if defined(Q_OS_WIN)
- // Windows CE is not capable of handling that many threads. On the emulator it is dead with 26 threads already.
-# if defined(Q_OS_WINCE)
- const int numThreads = 20;
-# else
// need to test lots of threads, so that we exceed MAXIMUM_WAIT_OBJECTS in qt_adopted_thread_watcher()
const int numThreads = 200;
-# endif
#else
const int numThreads = 5;
#endif
@@ -950,7 +934,6 @@ void tst_QThread::adoptMultipleThreadsOverlap()
QCOMPARE(recorder.activationCount.load(), numThreads);
}
-#ifndef Q_OS_WINCE
// Disconnects on WinCE
void tst_QThread::stressTest()
{
@@ -962,7 +945,6 @@ void tst_QThread::stressTest()
t.wait(one_minute);
}
}
-#endif
class Syncronizer : public QObject
{ Q_OBJECT
diff --git a/tests/auto/corelib/thread/qthreadonce/tst_qthreadonce.cpp b/tests/auto/corelib/thread/qthreadonce/tst_qthreadonce.cpp
index ba64bf2963..a9af182ed8 100644
--- a/tests/auto/corelib/thread/qthreadonce/tst_qthreadonce.cpp
+++ b/tests/auto/corelib/thread/qthreadonce/tst_qthreadonce.cpp
@@ -120,7 +120,7 @@ void tst_QThreadOnce::sameThread()
void tst_QThreadOnce::multipleThreads()
{
-#if defined(Q_OS_WINCE) || defined(Q_OS_VXWORKS)
+#if defined(Q_OS_VXWORKS)
const int NumberOfThreads = 20;
#else
const int NumberOfThreads = 100;
diff --git a/tests/auto/corelib/thread/qthreadstorage/tst_qthreadstorage.cpp b/tests/auto/corelib/thread/qthreadstorage/tst_qthreadstorage.cpp
index f3eba5c823..49a3b3e4db 100644
--- a/tests/auto/corelib/thread/qthreadstorage/tst_qthreadstorage.cpp
+++ b/tests/auto/corelib/thread/qthreadstorage/tst_qthreadstorage.cpp
@@ -40,10 +40,8 @@
#include <pthread.h>
#endif
#ifdef Q_OS_WIN
-#ifndef Q_OS_WINCE
-#include <process.h>
-#endif
-#include <windows.h>
+# include <process.h>
+# include <qt_windows.h>
#endif
class tst_QThreadStorage : public QObject
@@ -202,6 +200,13 @@ void testAdoptedThreadStorageWin(void *p)
}
QObject::connect(QThread::currentThread(), SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop()));
}
+#ifdef Q_OS_WINRT
+unsigned __stdcall testAdoptedThreadStorageWinRT(void *p)
+{
+ testAdoptedThreadStorageWin(p);
+ return 0;
+}
+#endif
void *testAdoptedThreadStorageUnix(void *pointers)
{
testAdoptedThreadStorageWin(pointers);
@@ -219,13 +224,14 @@ void tst_QThreadStorage::adoptedThreads()
const int state = pthread_create(&thread, 0, testAdoptedThreadStorageUnix, &pointers);
QCOMPARE(state, 0);
pthread_join(thread, 0);
-#elif defined Q_OS_WIN && !defined(Q_OS_WINRT)
+#elif defined Q_OS_WINRT
+ HANDLE thread;
+ thread = (HANDLE) _beginthreadex(NULL, 0, testAdoptedThreadStorageWinRT, &pointers, 0, 0);
+ QVERIFY(thread);
+ WaitForSingleObjectEx(thread, INFINITE, FALSE);
+#elif defined Q_OS_WIN
HANDLE thread;
-#if defined(Q_OS_WINCE)
- thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)testAdoptedThreadStorageWin, &pointers, 0, NULL);
-#else
thread = (HANDLE)_beginthread(testAdoptedThreadStorageWin, 0, &pointers);
-#endif
QVERIFY(thread);
WaitForSingleObject(thread, INFINITE);
#endif