summaryrefslogtreecommitdiffstats
path: root/tests/auto/qthread
diff options
context:
space:
mode:
authorHolger Ihrig <holger.ihrig@nokia.com>2011-08-26 12:56:14 +0200
committerHolger Ihrig <holger.ihrig@nokia.com>2011-09-01 12:54:58 +0200
commit82e715b2770258fa2c536aeae1f46c7fccdcdecf (patch)
treea4b9135effe2109b164f622314a6ffac6198a8f8 /tests/auto/qthread
parentc9a5ccb268b5e2b2ce0743989c44f808b538ba9b (diff)
Moving relevant tests to corelib/thread
Task-number: QTBUG-21066 Change-Id: Ia16fa8961f1a73f4da6709197b5dd9929c16583f Reviewed-on: http://codereview.qt.nokia.com/3663 Reviewed-by: Qt Sanity Bot <qt_sanity_bot@ovi.com> Reviewed-by: Rohan McGovern <rohan.mcgovern@nokia.com> Reviewed-by: Jason McDonald <jason.mcdonald@nokia.com>
Diffstat (limited to 'tests/auto/qthread')
-rw-r--r--tests/auto/qthread/.gitignore1
-rw-r--r--tests/auto/qthread/qthread.pro5
-rw-r--r--tests/auto/qthread/tst_qthread.cpp1249
3 files changed, 0 insertions, 1255 deletions
diff --git a/tests/auto/qthread/.gitignore b/tests/auto/qthread/.gitignore
deleted file mode 100644
index 4413a75588..0000000000
--- a/tests/auto/qthread/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-tst_qthread
diff --git a/tests/auto/qthread/qthread.pro b/tests/auto/qthread/qthread.pro
deleted file mode 100644
index d3b1028034..0000000000
--- a/tests/auto/qthread/qthread.pro
+++ /dev/null
@@ -1,5 +0,0 @@
-load(qttest_p4)
-SOURCES += tst_qthread.cpp
-QT = core
-symbian:LIBS += -llibpthread
-CONFIG += parallel_test
diff --git a/tests/auto/qthread/tst_qthread.cpp b/tests/auto/qthread/tst_qthread.cpp
deleted file mode 100644
index 3c46212c16..0000000000
--- a/tests/auto/qthread/tst_qthread.cpp
+++ /dev/null
@@ -1,1249 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** This file is part of the test suite of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** GNU Lesser General Public License Usage
-** 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, Nokia gives you certain additional
-** rights. These rights are described in the Nokia 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.
-**
-** Other Usage
-** Alternatively, this file may be used in accordance with the terms and
-** conditions contained in a signed written agreement between you and Nokia.
-**
-**
-**
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-
-#include <QtTest/QtTest>
-
-#include <qcoreapplication.h>
-#include <qdatetime.h>
-#include <qmutex.h>
-#include <qthread.h>
-#include <qtimer.h>
-#include <qwaitcondition.h>
-#include <qdebug.h>
-#include <qmetaobject.h>
-
-#ifdef Q_OS_UNIX
-#include <pthread.h>
-#endif
-#if defined(Q_OS_WINCE)
-#include <windows.h>
-#elif defined(Q_OS_WIN)
-#include <process.h>
-#include <windows.h>
-#endif
-
-//TESTED_CLASS=
-//TESTED_FILES=
-
-class tst_QThread : public QObject
-{
- Q_OBJECT
-
-public:
- tst_QThread();
- virtual ~tst_QThread();
-
-private slots:
- void currentThreadId();
- void currentThread();
- void idealThreadCount();
- void isFinished();
- void isRunning();
- void setPriority();
- void priority();
- void setStackSize();
- void stackSize();
- void exit();
- void start();
- void terminate();
- void quit();
- void wait();
- void started();
- void finished();
- void terminated();
- void run();
- void exec();
- void setTerminationEnabled();
- void sleep();
- void msleep();
- void usleep();
-
- void nativeThreadAdoption();
- void adoptedThreadAffinity();
- void adoptedThreadSetPriority();
- void adoptedThreadExit();
- void adoptedThreadExec();
- void adoptedThreadFinished();
- void adoptedThreadExecFinished();
- void adoptMultipleThreads();
- void adoptMultipleThreadsOverlap();
-
- void QTBUG13810_exitAndStart();
- void QTBUG15378_exitAndExec();
-
- void connectThreadFinishedSignalToObjectDeleteLaterSlot();
- void wait2();
- void wait3_slowDestructor();
- void destroyFinishRace();
- void startFinishRace();
- void startAndQuitCustomEventLoop();
-
- void stressTest();
-};
-
-enum { one_minute = 60 * 1000, five_minutes = 5 * one_minute };
-
-class SignalRecorder : public QObject
-{
- Q_OBJECT
-public:
- QAtomicInt activationCount;
-
- inline SignalRecorder()
- { activationCount = 0; }
-
- bool wasActivated()
- { return activationCount > 0; }
-
-public slots:
- void slot();
-};
-
-void SignalRecorder::slot()
-{ activationCount.ref(); }
-
-class Current_Thread : public QThread
-{
-public:
- Qt::HANDLE id;
- QThread *thread;
-
- void run()
- {
- id = QThread::currentThreadId();
- thread = QThread::currentThread();
- }
-};
-
-class Simple_Thread : public QThread
-{
-public:
- QMutex mutex;
- QWaitCondition cond;
-
- void run()
- {
- QMutexLocker locker(&mutex);
- cond.wakeOne();
- }
-};
-
-class Exit_Object : public QObject
-{
- Q_OBJECT
-public:
- QThread *thread;
- int code;
-public slots:
- void slot()
- { thread->exit(code); }
-};
-
-class Exit_Thread : public Simple_Thread
-{
-public:
- Exit_Object *object;
- int code;
- int result;
-
- void run()
- {
- Simple_Thread::run();
- if (object) {
- object->thread = this;
- object->code = code;
- QTimer::singleShot(100, object, SLOT(slot()));
- }
- result = exec();
- }
-};
-
-class Terminate_Thread : public Simple_Thread
-{
-public:
- void run()
- {
- setTerminationEnabled(false);
- {
- QMutexLocker locker(&mutex);
- cond.wakeOne();
- cond.wait(&mutex, five_minutes);
- }
- setTerminationEnabled(true);
- qFatal("tst_QThread: test case hung");
- }
-};
-
-class Quit_Object : public QObject
-{
- Q_OBJECT
-public:
- QThread *thread;
-public slots:
- void slot()
- { thread->quit(); }
-};
-
-class Quit_Thread : public Simple_Thread
-{
-public:
- Quit_Object *object;
- int result;
-
- void run()
- {
- Simple_Thread::run();
- if (object) {
- object->thread = this;
- QTimer::singleShot(100, object, SLOT(slot()));
- }
- result = exec();
- }
-};
-
-class Sleep_Thread : public Simple_Thread
-{
-public:
- enum SleepType { Second, Millisecond, Microsecond };
-
- SleepType sleepType;
- int interval;
-
- int elapsed; // result, in *MILLISECONDS*
-
- void run()
- {
- QMutexLocker locker(&mutex);
-
- elapsed = 0;
- QTime time;
- time.start();
- switch (sleepType) {
- case Second:
- sleep(interval);
- break;
- case Millisecond:
- msleep(interval);
- break;
- case Microsecond:
- usleep(interval);
- break;
- }
- elapsed = time.elapsed();
-
- cond.wakeOne();
- }
-};
-
-tst_QThread::tst_QThread()
-
-{
-}
-
-tst_QThread::~tst_QThread()
-{
-
-}
-
-void tst_QThread::currentThreadId()
-{
- Current_Thread thread;
- thread.id = 0;
- thread.thread = 0;
- thread.start();
- QVERIFY(thread.wait(five_minutes));
- QVERIFY(thread.id != 0);
- QVERIFY(thread.id != QThread::currentThreadId());
-}
-
-void tst_QThread::currentThread()
-{
- QVERIFY(QThread::currentThread() != 0);
- QCOMPARE(QThread::currentThread(), thread());
-
- Current_Thread thread;
- thread.id = 0;
- thread.thread = 0;
- thread.start();
- QVERIFY(thread.wait(five_minutes));
- QCOMPARE(thread.thread, (QThread *)&thread);
-}
-
-void tst_QThread::idealThreadCount()
-{
- QVERIFY(QThread::idealThreadCount() > 0);
- qDebug() << "Available cpu cores:" << QThread::idealThreadCount();
-}
-
-void tst_QThread::isFinished()
-{
- Simple_Thread thread;
- QVERIFY(!thread.isFinished());
- QMutexLocker locker(&thread.mutex);
- thread.start();
- QVERIFY(!thread.isFinished());
- thread.cond.wait(locker.mutex());
- QVERIFY(thread.wait(five_minutes));
- QVERIFY(thread.isFinished());
-}
-
-void tst_QThread::isRunning()
-{
- Simple_Thread thread;
- QVERIFY(!thread.isRunning());
- QMutexLocker locker(&thread.mutex);
- thread.start();
- QVERIFY(thread.isRunning());
- thread.cond.wait(locker.mutex());
- QVERIFY(thread.wait(five_minutes));
- QVERIFY(!thread.isRunning());
-}
-
-void tst_QThread::setPriority()
-{
- Simple_Thread thread;
-
- // cannot change the priority, since the thread is not running
- QCOMPARE(thread.priority(), QThread::InheritPriority);
- QTest::ignoreMessage(QtWarningMsg, "QThread::setPriority: Cannot set priority, thread is not running");
- thread.setPriority(QThread::IdlePriority);
- QCOMPARE(thread.priority(), QThread::InheritPriority);
- QTest::ignoreMessage(QtWarningMsg, "QThread::setPriority: Cannot set priority, thread is not running");
- thread.setPriority(QThread::LowestPriority);
- QCOMPARE(thread.priority(), QThread::InheritPriority);
- QTest::ignoreMessage(QtWarningMsg, "QThread::setPriority: Cannot set priority, thread is not running");
- thread.setPriority(QThread::LowPriority);
- QCOMPARE(thread.priority(), QThread::InheritPriority);
- QTest::ignoreMessage(QtWarningMsg, "QThread::setPriority: Cannot set priority, thread is not running");
- thread.setPriority(QThread::NormalPriority);
- QCOMPARE(thread.priority(), QThread::InheritPriority);
- QTest::ignoreMessage(QtWarningMsg, "QThread::setPriority: Cannot set priority, thread is not running");
- thread.setPriority(QThread::HighPriority);
- QCOMPARE(thread.priority(), QThread::InheritPriority);
- QTest::ignoreMessage(QtWarningMsg, "QThread::setPriority: Cannot set priority, thread is not running");
- thread.setPriority(QThread::HighestPriority);
- QCOMPARE(thread.priority(), QThread::InheritPriority);
- QTest::ignoreMessage(QtWarningMsg, "QThread::setPriority: Cannot set priority, thread is not running");
- thread.setPriority(QThread::TimeCriticalPriority);
- QCOMPARE(thread.priority(), QThread::InheritPriority);
-
- QCOMPARE(thread.priority(), QThread::InheritPriority);
- QMutexLocker locker(&thread.mutex);
- thread.start();
-
- // change the priority of a running thread
- QCOMPARE(thread.priority(), QThread::InheritPriority);
- thread.setPriority(QThread::IdlePriority);
- QCOMPARE(thread.priority(), QThread::IdlePriority);
- thread.setPriority(QThread::LowestPriority);
- QCOMPARE(thread.priority(), QThread::LowestPriority);
- thread.setPriority(QThread::LowPriority);
- QCOMPARE(thread.priority(), QThread::LowPriority);
- thread.setPriority(QThread::NormalPriority);
- QCOMPARE(thread.priority(), QThread::NormalPriority);
- thread.setPriority(QThread::HighPriority);
- QCOMPARE(thread.priority(), QThread::HighPriority);
- thread.setPriority(QThread::HighestPriority);
- QCOMPARE(thread.priority(), QThread::HighestPriority);
- thread.setPriority(QThread::TimeCriticalPriority);
- QCOMPARE(thread.priority(), QThread::TimeCriticalPriority);
- thread.cond.wait(locker.mutex());
- QVERIFY(thread.wait(five_minutes));
-
- QCOMPARE(thread.priority(), QThread::InheritPriority);
- QTest::ignoreMessage(QtWarningMsg, "QThread::setPriority: Cannot set priority, thread is not running");
- thread.setPriority(QThread::IdlePriority);
- QCOMPARE(thread.priority(), QThread::InheritPriority);
- QTest::ignoreMessage(QtWarningMsg, "QThread::setPriority: Cannot set priority, thread is not running");
- thread.setPriority(QThread::LowestPriority);
- QCOMPARE(thread.priority(), QThread::InheritPriority);
- QTest::ignoreMessage(QtWarningMsg, "QThread::setPriority: Cannot set priority, thread is not running");
- thread.setPriority(QThread::LowPriority);
- QCOMPARE(thread.priority(), QThread::InheritPriority);
- QTest::ignoreMessage(QtWarningMsg, "QThread::setPriority: Cannot set priority, thread is not running");
- thread.setPriority(QThread::NormalPriority);
- QCOMPARE(thread.priority(), QThread::InheritPriority);
- QTest::ignoreMessage(QtWarningMsg, "QThread::setPriority: Cannot set priority, thread is not running");
- thread.setPriority(QThread::HighPriority);
- QCOMPARE(thread.priority(), QThread::InheritPriority);
- QTest::ignoreMessage(QtWarningMsg, "QThread::setPriority: Cannot set priority, thread is not running");
- thread.setPriority(QThread::HighestPriority);
- QCOMPARE(thread.priority(), QThread::InheritPriority);
- QTest::ignoreMessage(QtWarningMsg, "QThread::setPriority: Cannot set priority, thread is not running");
- thread.setPriority(QThread::TimeCriticalPriority);
- QCOMPARE(thread.priority(), QThread::InheritPriority);
-}
-
-void tst_QThread::priority()
-{ DEPENDS_ON("setPriority"); }
-
-void tst_QThread::setStackSize()
-{
- Simple_Thread thread;
- QCOMPARE(thread.stackSize(), 0u);
- thread.setStackSize(8192u);
- QCOMPARE(thread.stackSize(), 8192u);
- thread.setStackSize(0u);
- QCOMPARE(thread.stackSize(), 0u);
-}
-
-void tst_QThread::stackSize()
-{
- DEPENDS_ON("setStackSize");
-}
-
-void tst_QThread::exit()
-{
- Exit_Thread thread;
- thread.object = new Exit_Object;
- thread.object->moveToThread(&thread);
- thread.code = 42;
- thread.result = 0;
- QVERIFY(!thread.isFinished());
- QVERIFY(!thread.isRunning());
- QMutexLocker locker(&thread.mutex);
- thread.start();
- QVERIFY(thread.isRunning());
- QVERIFY(!thread.isFinished());
- thread.cond.wait(locker.mutex());
- QVERIFY(thread.wait(five_minutes));
- QVERIFY(thread.isFinished());
- QVERIFY(!thread.isRunning());
- QCOMPARE(thread.result, thread.code);
- delete thread.object;
-
- Exit_Thread thread2;
- thread2.object = 0;
- thread2.code = 53;
- thread2.result = 0;
- QMutexLocker locker2(&thread2.mutex);
- thread2.start();
- thread2.exit(thread2.code);
- thread2.cond.wait(locker2.mutex());
- QVERIFY(thread2.wait(five_minutes));
- QCOMPARE(thread2.result, thread2.code);
-}
-
-void tst_QThread::start()
-{
- QThread::Priority priorities[] = {
- QThread::IdlePriority,
- QThread::LowestPriority,
- QThread::LowPriority,
- QThread::NormalPriority,
- QThread::HighPriority,
- QThread::HighestPriority,
- QThread::TimeCriticalPriority,
- QThread::InheritPriority
- };
- const int prio_count = sizeof(priorities) / sizeof(QThread::Priority);
-
- for (int i = 0; i < prio_count; ++i) {
- Simple_Thread thread;
- QVERIFY(!thread.isFinished());
- QVERIFY(!thread.isRunning());
- QMutexLocker locker(&thread.mutex);
- thread.start(priorities[i]);
- QVERIFY(thread.isRunning());
- QVERIFY(!thread.isFinished());
- thread.cond.wait(locker.mutex());
- QVERIFY(thread.wait(five_minutes));
- QVERIFY(thread.isFinished());
- QVERIFY(!thread.isRunning());
- }
-}
-
-void tst_QThread::terminate()
-{
- Terminate_Thread thread;
- {
- QMutexLocker locker(&thread.mutex);
- thread.start();
- QVERIFY(thread.cond.wait(locker.mutex(), five_minutes));
- thread.terminate();
- thread.cond.wakeOne();
- }
- QVERIFY(thread.wait(five_minutes));
-}
-
-void tst_QThread::quit()
-{
- Quit_Thread thread;
- thread.object = new Quit_Object;
- thread.object->moveToThread(&thread);
- thread.result = -1;
- QVERIFY(!thread.isFinished());
- QVERIFY(!thread.isRunning());
- QMutexLocker locker(&thread.mutex);
- thread.start();
- QVERIFY(thread.isRunning());
- QVERIFY(!thread.isFinished());
- thread.cond.wait(locker.mutex());
- QVERIFY(thread.wait(five_minutes));
- QVERIFY(thread.isFinished());
- QVERIFY(!thread.isRunning());
- QCOMPARE(thread.result, 0);
- delete thread.object;
-
- Quit_Thread thread2;
- thread2.object = 0;
- thread2.result = -1;
- QMutexLocker locker2(&thread2.mutex);
- thread2.start();
- thread2.quit();
- thread2.cond.wait(locker2.mutex());
- QVERIFY(thread2.wait(five_minutes));
- QCOMPARE(thread2.result, 0);
-}
-
-void tst_QThread::wait()
-{
- DEPENDS_ON("isRunning");
- DEPENDS_ON("isFinished");
-}
-
-void tst_QThread::started()
-{
- SignalRecorder recorder;
- Simple_Thread thread;
- connect(&thread, SIGNAL(started()), &recorder, SLOT(slot()), Qt::DirectConnection);
- thread.start();
- QVERIFY(thread.wait(five_minutes));
- QVERIFY(recorder.wasActivated());
-}
-
-void tst_QThread::finished()
-{
- SignalRecorder recorder;
- Simple_Thread thread;
- connect(&thread, SIGNAL(finished()), &recorder, SLOT(slot()), Qt::DirectConnection);
- thread.start();
- QVERIFY(thread.wait(five_minutes));
- QVERIFY(recorder.wasActivated());
-}
-
-void tst_QThread::terminated()
-{
- SignalRecorder recorder;
- Terminate_Thread thread;
- connect(&thread, SIGNAL(terminated()), &recorder, SLOT(slot()), Qt::DirectConnection);
- {
- QMutexLocker locker(&thread.mutex);
- thread.start();
- thread.cond.wait(locker.mutex());
- thread.terminate();
- thread.cond.wakeOne();
- }
- QVERIFY(thread.wait(five_minutes));
- QVERIFY(recorder.wasActivated());
-}
-
-void tst_QThread::run()
-{ DEPENDS_ON("wait()"); }
-
-void tst_QThread::exec()
-{
- DEPENDS_ON("exit()");
- DEPENDS_ON("quit()");
-
- class MultipleExecThread : public QThread
- {
- public:
- int res1, res2;
-
- MultipleExecThread() : res1(-2), res2(-2) { }
-
- void run()
- {
- {
- Exit_Object o;
- o.thread = this;
- o.code = 1;
- QTimer::singleShot(100, &o, SLOT(slot()));
- res1 = exec();
- }
- {
- Exit_Object o;
- o.thread = this;
- o.code = 2;
- QTimer::singleShot(100, &o, SLOT(slot()));
- res2 = exec();
- }
- }
- };
-
- MultipleExecThread thread;
- thread.start();
- QVERIFY(thread.wait());
-
- QCOMPARE(thread.res1, 1);
- QCOMPARE(thread.res2, 2);
-}
-
-void tst_QThread::setTerminationEnabled()
-{ DEPENDS_ON("terminate"); }
-
-void tst_QThread::sleep()
-{
- Sleep_Thread thread;
- thread.sleepType = Sleep_Thread::Second;
- thread.interval = 2;
- thread.start();
- QVERIFY(thread.wait(five_minutes));
- QVERIFY(thread.elapsed >= 2000);
-}
-
-void tst_QThread::msleep()
-{
- Sleep_Thread thread;
- thread.sleepType = Sleep_Thread::Millisecond;
- thread.interval = 120;
- thread.start();
- QVERIFY(thread.wait(five_minutes));
-#if defined (Q_OS_WIN)
- // Since the resolution of QTime is so coarse...
- QVERIFY(thread.elapsed >= 100);
-#else
- QVERIFY(thread.elapsed >= 120);
-#endif
-}
-
-void tst_QThread::usleep()
-{
- Sleep_Thread thread;
- thread.sleepType = Sleep_Thread::Microsecond;
- thread.interval = 120000;
- thread.start();
- QVERIFY(thread.wait(five_minutes));
-#if defined (Q_OS_WIN)
- // Since the resolution of QTime is so coarse...
- QVERIFY(thread.elapsed >= 100);
-#else
- QVERIFY(thread.elapsed >= 120);
-#endif
-}
-
-typedef void (*FunctionPointer)(void *);
-void noop(void*) { }
-
-#ifdef Q_OS_SYMBIAN
-typedef RThread ThreadHandle;
-#elif defined Q_OS_UNIX
- typedef pthread_t ThreadHandle;
-#elif defined Q_OS_WIN
- typedef HANDLE ThreadHandle;
-#endif
-
-#ifdef Q_OS_WIN
-#define WIN_FIX_STDCALL __stdcall
-#else
-#define WIN_FIX_STDCALL
-#endif
-
-class NativeThreadWrapper
-{
-public:
- NativeThreadWrapper() : qthread(0), waitForStop(false) {}
- void start(FunctionPointer functionPointer = noop, void *data = 0);
- void startAndWait(FunctionPointer functionPointer = noop, void *data = 0);
- void join();
- void setWaitForStop() { waitForStop = true; }
- void stop();
-
- ThreadHandle nativeThreadHandle;
- QThread *qthread;
- QWaitCondition startCondition;
- QMutex mutex;
- bool waitForStop;
- QWaitCondition stopCondition;
-protected:
- static void *runUnix(void *data);
- static unsigned WIN_FIX_STDCALL runWin(void *data);
- static int runSymbian(void *data);
-
- FunctionPointer functionPointer;
- void *data;
-};
-
-void NativeThreadWrapper::start(FunctionPointer functionPointer, void *data)
-{
- this->functionPointer = functionPointer;
- this->data = data;
-#ifdef Q_OS_SYMBIAN
- qt_symbian_throwIfError(nativeThreadHandle.Create(KNullDesC(), NativeThreadWrapper::runSymbian, 1024, &User::Allocator(), this));
- nativeThreadHandle.Resume();
-#elif defined Q_OS_UNIX
- const int state = pthread_create(&nativeThreadHandle, 0, NativeThreadWrapper::runUnix, this);
- Q_UNUSED(state);
-#elif defined(Q_OS_WINCE)
- nativeThreadHandle = CreateThread(NULL, 0 , (LPTHREAD_START_ROUTINE)NativeThreadWrapper::runWin , this, 0, NULL);
-#elif defined Q_OS_WIN
- unsigned thrdid = 0;
- nativeThreadHandle = (Qt::HANDLE) _beginthreadex(NULL, 0, NativeThreadWrapper::runWin, this, 0, &thrdid);
-#endif
-}
-
-void NativeThreadWrapper::startAndWait(FunctionPointer functionPointer, void *data)
-{
- QMutexLocker locker(&mutex);
- start(functionPointer, data);
- startCondition.wait(locker.mutex());
-}
-
-void NativeThreadWrapper::join()
-{
-#ifdef Q_OS_SYMBIAN
- TRequestStatus stat;
- nativeThreadHandle.Logon(stat);
- User::WaitForRequest(stat);
- nativeThreadHandle.Close();
-#elif defined Q_OS_UNIX
- pthread_join(nativeThreadHandle, 0);
-#elif defined Q_OS_WIN
- WaitForSingleObject(nativeThreadHandle, INFINITE);
- CloseHandle(nativeThreadHandle);
-#endif
-}
-
-void *NativeThreadWrapper::runUnix(void *that)
-{
- NativeThreadWrapper *nativeThreadWrapper = reinterpret_cast<NativeThreadWrapper*>(that);
-
- // Adopt thread, create QThread object.
- nativeThreadWrapper->qthread = QThread::currentThread();
-
- // Release main thread.
- {
- QMutexLocker lock(&nativeThreadWrapper->mutex);
- nativeThreadWrapper->startCondition.wakeOne();
- }
-
- // Run function.
- nativeThreadWrapper->functionPointer(nativeThreadWrapper->data);
-
- // Wait for stop.
- {
- QMutexLocker lock(&nativeThreadWrapper->mutex);
- if (nativeThreadWrapper->waitForStop)
- nativeThreadWrapper->stopCondition.wait(lock.mutex());
- }
-
- return 0;
-}
-
-unsigned WIN_FIX_STDCALL NativeThreadWrapper::runWin(void *data)
-{
- runUnix(data);
- return 0;
-}
-
-int NativeThreadWrapper::runSymbian(void *data)
-{
- runUnix(data);
- return 0;
-}
-
-void NativeThreadWrapper::stop()
-{
- QMutexLocker lock(&mutex);
- waitForStop = false;
- stopCondition.wakeOne();
-}
-
-bool threadAdoptedOk = false;
-QThread *mainThread;
-void testNativeThreadAdoption(void *)
-{
- threadAdoptedOk = (QThread::currentThreadId() != 0
- && QThread::currentThread() != 0
- && QThread::currentThread() != mainThread);
-}
-void tst_QThread::nativeThreadAdoption()
-{
- threadAdoptedOk = false;
- mainThread = QThread::currentThread();
- NativeThreadWrapper nativeThread;
- nativeThread.setWaitForStop();
- nativeThread.startAndWait(testNativeThreadAdoption);
- QVERIFY(nativeThread.qthread);
-
- nativeThread.stop();
- nativeThread.join();
-
- QVERIFY(threadAdoptedOk);
-}
-
-void adoptedThreadAffinityFunction(void *arg)
-{
- QThread **affinity = reinterpret_cast<QThread **>(arg);
- QThread *current = QThread::currentThread();
- affinity[0] = current;
- affinity[1] = current->thread();
-}
-
-void tst_QThread::adoptedThreadAffinity()
-{
- QThread *affinity[2] = { 0, 0 };
-
- NativeThreadWrapper thread;
- thread.startAndWait(adoptedThreadAffinityFunction, affinity);
- thread.join();
-
- // adopted thread should have affinity to itself
- QCOMPARE(affinity[0], affinity[1]);
-}
-
-void tst_QThread::adoptedThreadSetPriority()
-{
-
- NativeThreadWrapper nativeThread;
- nativeThread.setWaitForStop();
- nativeThread.startAndWait();
-
- // change the priority of a running thread
- QCOMPARE(nativeThread.qthread->priority(), QThread::InheritPriority);
- nativeThread.qthread->setPriority(QThread::IdlePriority);
- QCOMPARE(nativeThread.qthread->priority(), QThread::IdlePriority);
- nativeThread.qthread->setPriority(QThread::LowestPriority);
- QCOMPARE(nativeThread.qthread->priority(), QThread::LowestPriority);
- nativeThread.qthread->setPriority(QThread::LowPriority);
- QCOMPARE(nativeThread.qthread->priority(), QThread::LowPriority);
- nativeThread.qthread->setPriority(QThread::NormalPriority);
- QCOMPARE(nativeThread.qthread->priority(), QThread::NormalPriority);
- nativeThread.qthread->setPriority(QThread::HighPriority);
- QCOMPARE(nativeThread.qthread->priority(), QThread::HighPriority);
- nativeThread.qthread->setPriority(QThread::HighestPriority);
- QCOMPARE(nativeThread.qthread->priority(), QThread::HighestPriority);
- nativeThread.qthread->setPriority(QThread::TimeCriticalPriority);
- QCOMPARE(nativeThread.qthread->priority(), QThread::TimeCriticalPriority);
-
- nativeThread.stop();
- nativeThread.join();
-}
-
-void tst_QThread::adoptedThreadExit()
-{
- NativeThreadWrapper nativeThread;
- nativeThread.setWaitForStop();
-
- nativeThread.startAndWait();
- QVERIFY(nativeThread.qthread);
- QVERIFY(nativeThread.qthread->isRunning());
- QVERIFY(!nativeThread.qthread->isFinished());
-
- nativeThread.stop();
- nativeThread.join();
-}
-
-void adoptedThreadExecFunction(void *)
-{
- QThread * const adoptedThread = QThread::currentThread();
- QEventLoop eventLoop(adoptedThread);
-
- const int code = 1;
- Exit_Object o;
- o.thread = adoptedThread;
- o.code = code;
- QTimer::singleShot(100, &o, SLOT(slot()));
-
- const int result = eventLoop.exec();
- QCOMPARE(result, code);
-}
-
-void tst_QThread::adoptedThreadExec()
-{
- NativeThreadWrapper nativeThread;
- nativeThread.start(adoptedThreadExecFunction);
- nativeThread.join();
-}
-
-/*
- Test that you get the finished signal when an adopted thread exits.
-*/
-void tst_QThread::adoptedThreadFinished()
-{
- NativeThreadWrapper nativeThread;
- nativeThread.setWaitForStop();
- nativeThread.startAndWait();
-
- QObject::connect(nativeThread.qthread, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop()));
-
- nativeThread.stop();
- nativeThread.join();
-
- QTestEventLoop::instance().enterLoop(5);
- QVERIFY(!QTestEventLoop::instance().timeout());
-}
-
-void tst_QThread::adoptedThreadExecFinished()
-{
- NativeThreadWrapper nativeThread;
- nativeThread.setWaitForStop();
- nativeThread.startAndWait(adoptedThreadExecFunction);
-
- QObject::connect(nativeThread.qthread, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop()));
-
- nativeThread.stop();
- nativeThread.join();
-
- QTestEventLoop::instance().enterLoop(5);
- QVERIFY(!QTestEventLoop::instance().timeout());
-}
-
-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
- QVector<NativeThreadWrapper*> nativeThreads;
-
- SignalRecorder recorder;
-
- for (int i = 0; i < numThreads; ++i) {
- nativeThreads.append(new NativeThreadWrapper());
- nativeThreads.at(i)->setWaitForStop();
- nativeThreads.at(i)->startAndWait();
- QObject::connect(nativeThreads.at(i)->qthread, SIGNAL(finished()), &recorder, SLOT(slot()));
- }
-
- QObject::connect(nativeThreads.at(numThreads - 1)->qthread, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop()));
-
- for (int i = 0; i < numThreads; ++i) {
- nativeThreads.at(i)->stop();
- nativeThreads.at(i)->join();
- delete nativeThreads.at(i);
- }
-
- QTestEventLoop::instance().enterLoop(5);
- QVERIFY(!QTestEventLoop::instance().timeout());
- QCOMPARE(int(recorder.activationCount), numThreads);
-}
-
-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
-#elif defined(Q_OS_SYMBIAN)
- // stress the monitoring thread's add function
- const int numThreads = 100;
-#else
- const int numThreads = 5;
-#endif
- QVector<NativeThreadWrapper*> nativeThreads;
-
- SignalRecorder recorder;
-
- for (int i = 0; i < numThreads; ++i) {
- nativeThreads.append(new NativeThreadWrapper());
- nativeThreads.at(i)->setWaitForStop();
- nativeThreads.at(i)->mutex.lock();
- nativeThreads.at(i)->start();
- }
- for (int i = 0; i < numThreads; ++i) {
- nativeThreads.at(i)->startCondition.wait(&nativeThreads.at(i)->mutex);
- QObject::connect(nativeThreads.at(i)->qthread, SIGNAL(finished()), &recorder, SLOT(slot()));
- nativeThreads.at(i)->mutex.unlock();
- }
-
- QObject::connect(nativeThreads.at(numThreads - 1)->qthread, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop()));
-
- for (int i = 0; i < numThreads; ++i) {
- nativeThreads.at(i)->stop();
- nativeThreads.at(i)->join();
- delete nativeThreads.at(i);
- }
-
- QTestEventLoop::instance().enterLoop(5);
- QVERIFY(!QTestEventLoop::instance().timeout());
- QCOMPARE(int(recorder.activationCount), numThreads);
-}
-void tst_QThread::stressTest()
-{
-#if defined(Q_OS_WINCE)
- QSKIP("Disconnects on WinCE, skipping...", SkipAll);
-#endif
- QTime t;
- t.start();
- while (t.elapsed() < one_minute) {
- Current_Thread t;
- t.start();
- t.wait(one_minute);
- }
-}
-
-class Syncronizer : public QObject
-{ Q_OBJECT
-public slots:
- void setProp(int p) {
- if(m_prop != p) {
- m_prop = p;
- emit propChanged(p);
- }
- }
-signals:
- void propChanged(int);
-public:
- Syncronizer() : m_prop(42) {}
- int m_prop;
-};
-
-void tst_QThread::QTBUG13810_exitAndStart()
-{
- QThread thread;
- thread.exit(555); //should do nothing
-
- thread.start();
-
- //test that the thread is running by executing queued connected signal there
- Syncronizer sync1;
- sync1.moveToThread(&thread);
- Syncronizer sync2;
- sync2.moveToThread(&thread);
- connect(&sync2, SIGNAL(propChanged(int)), &sync1, SLOT(setProp(int)), Qt::QueuedConnection);
- connect(&sync1, SIGNAL(propChanged(int)), &thread, SLOT(quit()), Qt::QueuedConnection);
- QMetaObject::invokeMethod(&sync2, "setProp", Qt::QueuedConnection , Q_ARG(int, 89));
- QTest::qWait(50);
- while(!thread.wait(10))
- QTest::qWait(10);
- QCOMPARE(sync2.m_prop, 89);
- QCOMPARE(sync1.m_prop, 89);
-}
-
-void tst_QThread::QTBUG15378_exitAndExec()
-{
- class Thread : public QThread {
- public:
- QSemaphore sem1;
- QSemaphore sem2;
- volatile int value;
- void run() {
- sem1.acquire();
- value = exec(); //First entrence
- sem2.release();
- value = exec(); // Second loop
- }
- };
- Thread thread;
- thread.value = 0;
- thread.start();
- thread.exit(556);
- thread.sem1.release(); //should exit the first loop
- thread.sem2.acquire();
- int v = thread.value;
- QCOMPARE(v, 556);
-
- //test that the thread is running by executing queued connected signal there
- Syncronizer sync1;
- sync1.moveToThread(&thread);
- Syncronizer sync2;
- sync2.moveToThread(&thread);
- connect(&sync2, SIGNAL(propChanged(int)), &sync1, SLOT(setProp(int)), Qt::QueuedConnection);
- connect(&sync1, SIGNAL(propChanged(int)), &thread, SLOT(quit()), Qt::QueuedConnection);
- QMetaObject::invokeMethod(&sync2, "setProp", Qt::QueuedConnection , Q_ARG(int, 89));
- QTest::qWait(50);
- while(!thread.wait(10))
- QTest::qWait(10);
- QCOMPARE(sync2.m_prop, 89);
- QCOMPARE(sync1.m_prop, 89);
-}
-
-void tst_QThread::connectThreadFinishedSignalToObjectDeleteLaterSlot()
-{
- QThread thread;
- QObject *object = new QObject;
- QWeakPointer<QObject> p = object;
- QVERIFY(!p.isNull());
- connect(&thread, SIGNAL(started()), &thread, SLOT(quit()), Qt::DirectConnection);
- connect(&thread, SIGNAL(finished()), object, SLOT(deleteLater()));
- object->moveToThread(&thread);
- thread.start();
- QVERIFY(thread.wait(30000));
- QVERIFY(p.isNull());
-}
-
-class Waiting_Thread : public QThread
-{
-public:
- enum { WaitTime = 800 };
- QMutex mutex;
- QWaitCondition cond1;
- QWaitCondition cond2;
-
- void run()
- {
- QMutexLocker locker(&mutex);
- cond1.wait(&mutex);
- cond2.wait(&mutex, WaitTime);
- }
-};
-
-void tst_QThread::wait2()
-{
- QElapsedTimer timer;
- Waiting_Thread thread;
- thread.start();
- timer.start();
- QVERIFY(!thread.wait(Waiting_Thread::WaitTime));
- qint64 elapsed = timer.elapsed();
-
- QVERIFY(elapsed >= Waiting_Thread::WaitTime);
- //QVERIFY(elapsed < Waiting_Thread::WaitTime * 1.4);
-
- timer.start();
- thread.cond1.wakeOne();
- QVERIFY(thread.wait(/*Waiting_Thread::WaitTime * 1.4*/));
- elapsed = timer.elapsed();
- QVERIFY(elapsed >= Waiting_Thread::WaitTime);
- //QVERIFY(elapsed < Waiting_Thread::WaitTime * 1.4);
-}
-
-
-class SlowSlotObject : public QObject {
- Q_OBJECT
-public:
- QMutex mutex;
- QWaitCondition cond;
-public slots:
- void slowSlot() {
- QMutexLocker locker(&mutex);
- cond.wait(&mutex);
- }
-};
-
-void tst_QThread::wait3_slowDestructor()
-{
- SlowSlotObject slow;
- QThread thread;
- QObject::connect(&thread, SIGNAL(finished()), &slow, SLOT(slowSlot()), Qt::DirectConnection);
-
- enum { WaitTime = 1800 };
- QElapsedTimer timer;
-
- thread.start();
- thread.quit();
- //the quit function will cause the thread to finish and enter the slowSlot that is blocking
-
- timer.start();
- QVERIFY(!thread.wait(Waiting_Thread::WaitTime));
- qint64 elapsed = timer.elapsed();
-
- QVERIFY(elapsed >= Waiting_Thread::WaitTime);
- //QVERIFY(elapsed < Waiting_Thread::WaitTime * 1.4);
-
- slow.cond.wakeOne();
- //now the thread should finish quickly
- QVERIFY(thread.wait(one_minute));
-}
-
-void tst_QThread::destroyFinishRace()
-{
- class Thread : public QThread { void run() {} };
- for (int i = 0; i < 15; i++) {
- Thread *thr = new Thread;
- connect(thr, SIGNAL(finished()), thr, SLOT(deleteLater()));
- QWeakPointer<QThread> weak(static_cast<QThread*>(thr));
- thr->start();
- while (weak) {
- qApp->processEvents();
- qApp->processEvents();
- qApp->processEvents();
- qApp->processEvents();
- }
- }
-}
-
-void tst_QThread::startFinishRace()
-{
- class Thread : public QThread {
- public:
- Thread() : i (50) {}
- void run() {
- i--;
- if (!i) disconnect(this, SIGNAL(finished()), 0, 0);
- }
- int i;
- };
- for (int i = 0; i < 15; i++) {
- Thread thr;
- connect(&thr, SIGNAL(finished()), &thr, SLOT(start()));
- thr.start();
- while (!thr.isFinished() || thr.i != 0) {
- qApp->processEvents();
- qApp->processEvents();
- qApp->processEvents();
- qApp->processEvents();
- }
- QCOMPARE(thr.i, 0);
- }
-}
-
-void tst_QThread::startAndQuitCustomEventLoop()
-{
- struct Thread : QThread {
- void run() { QEventLoop().exec(); }
- };
-
- for (int i = 0; i < 5; i++) {
- Thread t;
- t.start();
- t.quit();
- t.wait();
- }
-}
-
-
-QTEST_MAIN(tst_QThread)
-#include "tst_qthread.moc"