1 /****************************************************************************
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
6 ** This file is part of the test suite of the Qt Toolkit.
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
40 ****************************************************************************/
42 #include <QtTest/QtTest>
44 #include <qcoreapplication.h>
45 #include <qdatetime.h>
49 #include <qwaitcondition.h>
51 #include <qmetaobject.h>
56 #if defined(Q_OS_WINCE)
58 #elif defined(Q_OS_WIN)
63 class tst_QThread : public QObject
67 void currentThreadId();
69 void idealThreadCount();
86 void nativeThreadAdoption();
87 void adoptedThreadAffinity();
88 void adoptedThreadSetPriority();
89 void adoptedThreadExit();
90 void adoptedThreadExec();
91 void adoptedThreadFinished();
92 void adoptedThreadExecFinished();
93 void adoptMultipleThreads();
94 void adoptMultipleThreadsOverlap();
99 void connectThreadFinishedSignalToObjectDeleteLaterSlot();
101 void wait3_slowDestructor();
102 void destroyFinishRace();
103 void startFinishRace();
104 void startAndQuitCustomEventLoop();
105 void isRunningInFinished();
107 void customEventDispatcher();
114 enum { one_minute = 60 * 1000, five_minutes = 5 * one_minute };
116 class SignalRecorder : public QObject
120 QAtomicInt activationCount;
122 inline SignalRecorder()
127 { return activationCount.load() > 0; }
133 void SignalRecorder::slot()
134 { activationCount.ref(); }
136 class Current_Thread : public QThread
144 id = QThread::currentThreadId();
145 thread = QThread::currentThread();
149 class Simple_Thread : public QThread
157 QMutexLocker locker(&mutex);
162 class Exit_Object : public QObject
170 { thread->exit(code); }
173 class Exit_Thread : public Simple_Thread
182 Simple_Thread::run();
184 object->thread = this;
186 QTimer::singleShot(100, object, SLOT(slot()));
192 class Terminate_Thread : public Simple_Thread
197 setTerminationEnabled(false);
199 QMutexLocker locker(&mutex);
201 cond.wait(&mutex, five_minutes);
203 setTerminationEnabled(true);
204 qFatal("tst_QThread: test case hung");
208 class Quit_Object : public QObject
218 class Quit_Thread : public Simple_Thread
226 Simple_Thread::run();
228 object->thread = this;
229 QTimer::singleShot(100, object, SLOT(slot()));
235 class Sleep_Thread : public Simple_Thread
238 enum SleepType { Second, Millisecond, Microsecond };
243 int elapsed; // result, in *MILLISECONDS*
247 QMutexLocker locker(&mutex);
263 elapsed = time.elapsed();
269 void tst_QThread::currentThreadId()
271 Current_Thread thread;
275 QVERIFY(thread.wait(five_minutes));
276 QVERIFY(thread.id != 0);
277 QVERIFY(thread.id != QThread::currentThreadId());
280 void tst_QThread::currentThread()
282 QVERIFY(QThread::currentThread() != 0);
283 QCOMPARE(QThread::currentThread(), thread());
285 Current_Thread thread;
289 QVERIFY(thread.wait(five_minutes));
290 QCOMPARE(thread.thread, (QThread *)&thread);
293 void tst_QThread::idealThreadCount()
295 QVERIFY(QThread::idealThreadCount() > 0);
296 qDebug() << "Ideal thread count:" << QThread::idealThreadCount();
299 void tst_QThread::isFinished()
301 Simple_Thread thread;
302 QVERIFY(!thread.isFinished());
303 QMutexLocker locker(&thread.mutex);
305 QVERIFY(!thread.isFinished());
306 thread.cond.wait(locker.mutex());
307 QVERIFY(thread.wait(five_minutes));
308 QVERIFY(thread.isFinished());
311 void tst_QThread::isRunning()
313 Simple_Thread thread;
314 QVERIFY(!thread.isRunning());
315 QMutexLocker locker(&thread.mutex);
317 QVERIFY(thread.isRunning());
318 thread.cond.wait(locker.mutex());
319 QVERIFY(thread.wait(five_minutes));
320 QVERIFY(!thread.isRunning());
323 void tst_QThread::setPriority()
325 Simple_Thread thread;
327 // cannot change the priority, since the thread is not running
328 QCOMPARE(thread.priority(), QThread::InheritPriority);
329 QTest::ignoreMessage(QtWarningMsg, "QThread::setPriority: Cannot set priority, thread is not running");
330 thread.setPriority(QThread::IdlePriority);
331 QCOMPARE(thread.priority(), QThread::InheritPriority);
332 QTest::ignoreMessage(QtWarningMsg, "QThread::setPriority: Cannot set priority, thread is not running");
333 thread.setPriority(QThread::LowestPriority);
334 QCOMPARE(thread.priority(), QThread::InheritPriority);
335 QTest::ignoreMessage(QtWarningMsg, "QThread::setPriority: Cannot set priority, thread is not running");
336 thread.setPriority(QThread::LowPriority);
337 QCOMPARE(thread.priority(), QThread::InheritPriority);
338 QTest::ignoreMessage(QtWarningMsg, "QThread::setPriority: Cannot set priority, thread is not running");
339 thread.setPriority(QThread::NormalPriority);
340 QCOMPARE(thread.priority(), QThread::InheritPriority);
341 QTest::ignoreMessage(QtWarningMsg, "QThread::setPriority: Cannot set priority, thread is not running");
342 thread.setPriority(QThread::HighPriority);
343 QCOMPARE(thread.priority(), QThread::InheritPriority);
344 QTest::ignoreMessage(QtWarningMsg, "QThread::setPriority: Cannot set priority, thread is not running");
345 thread.setPriority(QThread::HighestPriority);
346 QCOMPARE(thread.priority(), QThread::InheritPriority);
347 QTest::ignoreMessage(QtWarningMsg, "QThread::setPriority: Cannot set priority, thread is not running");
348 thread.setPriority(QThread::TimeCriticalPriority);
349 QCOMPARE(thread.priority(), QThread::InheritPriority);
351 QCOMPARE(thread.priority(), QThread::InheritPriority);
352 QMutexLocker locker(&thread.mutex);
355 // change the priority of a running thread
356 QCOMPARE(thread.priority(), QThread::InheritPriority);
357 thread.setPriority(QThread::IdlePriority);
358 QCOMPARE(thread.priority(), QThread::IdlePriority);
359 thread.setPriority(QThread::LowestPriority);
360 QCOMPARE(thread.priority(), QThread::LowestPriority);
361 thread.setPriority(QThread::LowPriority);
362 QCOMPARE(thread.priority(), QThread::LowPriority);
363 thread.setPriority(QThread::NormalPriority);
364 QCOMPARE(thread.priority(), QThread::NormalPriority);
365 thread.setPriority(QThread::HighPriority);
366 QCOMPARE(thread.priority(), QThread::HighPriority);
367 thread.setPriority(QThread::HighestPriority);
368 QCOMPARE(thread.priority(), QThread::HighestPriority);
369 thread.setPriority(QThread::TimeCriticalPriority);
370 QCOMPARE(thread.priority(), QThread::TimeCriticalPriority);
371 thread.cond.wait(locker.mutex());
372 QVERIFY(thread.wait(five_minutes));
374 QCOMPARE(thread.priority(), QThread::InheritPriority);
375 QTest::ignoreMessage(QtWarningMsg, "QThread::setPriority: Cannot set priority, thread is not running");
376 thread.setPriority(QThread::IdlePriority);
377 QCOMPARE(thread.priority(), QThread::InheritPriority);
378 QTest::ignoreMessage(QtWarningMsg, "QThread::setPriority: Cannot set priority, thread is not running");
379 thread.setPriority(QThread::LowestPriority);
380 QCOMPARE(thread.priority(), QThread::InheritPriority);
381 QTest::ignoreMessage(QtWarningMsg, "QThread::setPriority: Cannot set priority, thread is not running");
382 thread.setPriority(QThread::LowPriority);
383 QCOMPARE(thread.priority(), QThread::InheritPriority);
384 QTest::ignoreMessage(QtWarningMsg, "QThread::setPriority: Cannot set priority, thread is not running");
385 thread.setPriority(QThread::NormalPriority);
386 QCOMPARE(thread.priority(), QThread::InheritPriority);
387 QTest::ignoreMessage(QtWarningMsg, "QThread::setPriority: Cannot set priority, thread is not running");
388 thread.setPriority(QThread::HighPriority);
389 QCOMPARE(thread.priority(), QThread::InheritPriority);
390 QTest::ignoreMessage(QtWarningMsg, "QThread::setPriority: Cannot set priority, thread is not running");
391 thread.setPriority(QThread::HighestPriority);
392 QCOMPARE(thread.priority(), QThread::InheritPriority);
393 QTest::ignoreMessage(QtWarningMsg, "QThread::setPriority: Cannot set priority, thread is not running");
394 thread.setPriority(QThread::TimeCriticalPriority);
395 QCOMPARE(thread.priority(), QThread::InheritPriority);
398 void tst_QThread::setStackSize()
400 Simple_Thread thread;
401 QCOMPARE(thread.stackSize(), 0u);
402 thread.setStackSize(8192u);
403 QCOMPARE(thread.stackSize(), 8192u);
404 thread.setStackSize(0u);
405 QCOMPARE(thread.stackSize(), 0u);
408 void tst_QThread::exit()
411 thread.object = new Exit_Object;
412 thread.object->moveToThread(&thread);
415 QVERIFY(!thread.isFinished());
416 QVERIFY(!thread.isRunning());
417 QMutexLocker locker(&thread.mutex);
419 QVERIFY(thread.isRunning());
420 QVERIFY(!thread.isFinished());
421 thread.cond.wait(locker.mutex());
422 QVERIFY(thread.wait(five_minutes));
423 QVERIFY(thread.isFinished());
424 QVERIFY(!thread.isRunning());
425 QCOMPARE(thread.result, thread.code);
426 delete thread.object;
432 QMutexLocker locker2(&thread2.mutex);
434 thread2.exit(thread2.code);
435 thread2.cond.wait(locker2.mutex());
436 QVERIFY(thread2.wait(five_minutes));
437 QCOMPARE(thread2.result, thread2.code);
440 void tst_QThread::start()
442 QThread::Priority priorities[] = {
443 QThread::IdlePriority,
444 QThread::LowestPriority,
445 QThread::LowPriority,
446 QThread::NormalPriority,
447 QThread::HighPriority,
448 QThread::HighestPriority,
449 QThread::TimeCriticalPriority,
450 QThread::InheritPriority
452 const int prio_count = sizeof(priorities) / sizeof(QThread::Priority);
454 for (int i = 0; i < prio_count; ++i) {
455 Simple_Thread thread;
456 QVERIFY(!thread.isFinished());
457 QVERIFY(!thread.isRunning());
458 QMutexLocker locker(&thread.mutex);
459 thread.start(priorities[i]);
460 QVERIFY(thread.isRunning());
461 QVERIFY(!thread.isFinished());
462 thread.cond.wait(locker.mutex());
463 QVERIFY(thread.wait(five_minutes));
464 QVERIFY(thread.isFinished());
465 QVERIFY(!thread.isRunning());
469 void tst_QThread::terminate()
471 Terminate_Thread thread;
473 QMutexLocker locker(&thread.mutex);
475 QVERIFY(thread.cond.wait(locker.mutex(), five_minutes));
477 thread.cond.wakeOne();
479 QVERIFY(thread.wait(five_minutes));
482 void tst_QThread::quit()
485 thread.object = new Quit_Object;
486 thread.object->moveToThread(&thread);
488 QVERIFY(!thread.isFinished());
489 QVERIFY(!thread.isRunning());
490 QMutexLocker locker(&thread.mutex);
492 QVERIFY(thread.isRunning());
493 QVERIFY(!thread.isFinished());
494 thread.cond.wait(locker.mutex());
495 QVERIFY(thread.wait(five_minutes));
496 QVERIFY(thread.isFinished());
497 QVERIFY(!thread.isRunning());
498 QCOMPARE(thread.result, 0);
499 delete thread.object;
504 QMutexLocker locker2(&thread2.mutex);
507 thread2.cond.wait(locker2.mutex());
508 QVERIFY(thread2.wait(five_minutes));
509 QCOMPARE(thread2.result, 0);
512 void tst_QThread::started()
514 SignalRecorder recorder;
515 Simple_Thread thread;
516 connect(&thread, SIGNAL(started()), &recorder, SLOT(slot()), Qt::DirectConnection);
518 QVERIFY(thread.wait(five_minutes));
519 QVERIFY(recorder.wasActivated());
522 void tst_QThread::finished()
524 SignalRecorder recorder;
525 Simple_Thread thread;
526 connect(&thread, SIGNAL(finished()), &recorder, SLOT(slot()), Qt::DirectConnection);
528 QVERIFY(thread.wait(five_minutes));
529 QVERIFY(recorder.wasActivated());
532 void tst_QThread::terminated()
534 SignalRecorder recorder;
535 Terminate_Thread thread;
536 connect(&thread, SIGNAL(terminated()), &recorder, SLOT(slot()), Qt::DirectConnection);
538 QMutexLocker locker(&thread.mutex);
540 thread.cond.wait(locker.mutex());
542 thread.cond.wakeOne();
544 QVERIFY(thread.wait(five_minutes));
545 QVERIFY(recorder.wasActivated());
548 void tst_QThread::exec()
550 class MultipleExecThread : public QThread
555 MultipleExecThread() : res1(-2), res2(-2) { }
563 QTimer::singleShot(100, &o, SLOT(slot()));
570 QTimer::singleShot(100, &o, SLOT(slot()));
576 MultipleExecThread thread;
578 QVERIFY(thread.wait());
580 QCOMPARE(thread.res1, 1);
581 QCOMPARE(thread.res2, 2);
584 void tst_QThread::sleep()
587 thread.sleepType = Sleep_Thread::Second;
590 QVERIFY(thread.wait(five_minutes));
591 QVERIFY(thread.elapsed >= 2000);
594 void tst_QThread::msleep()
597 thread.sleepType = Sleep_Thread::Millisecond;
598 thread.interval = 120;
600 QVERIFY(thread.wait(five_minutes));
601 #if defined (Q_OS_WIN)
602 // Since the resolution of QTime is so coarse...
603 QVERIFY(thread.elapsed >= 100);
605 QVERIFY(thread.elapsed >= 120);
609 void tst_QThread::usleep()
612 thread.sleepType = Sleep_Thread::Microsecond;
613 thread.interval = 120000;
615 QVERIFY(thread.wait(five_minutes));
616 #if defined (Q_OS_WIN)
617 // Since the resolution of QTime is so coarse...
618 QVERIFY(thread.elapsed >= 100);
620 QVERIFY(thread.elapsed >= 120);
624 typedef void (*FunctionPointer)(void *);
627 #if defined Q_OS_UNIX
628 typedef pthread_t ThreadHandle;
629 #elif defined Q_OS_WIN
630 typedef HANDLE ThreadHandle;
634 #define WIN_FIX_STDCALL __stdcall
636 #define WIN_FIX_STDCALL
639 class NativeThreadWrapper
642 NativeThreadWrapper() : qthread(0), waitForStop(false) {}
643 void start(FunctionPointer functionPointer = noop, void *data = 0);
644 void startAndWait(FunctionPointer functionPointer = noop, void *data = 0);
646 void setWaitForStop() { waitForStop = true; }
649 ThreadHandle nativeThreadHandle;
651 QWaitCondition startCondition;
654 QWaitCondition stopCondition;
656 static void *runUnix(void *data);
657 static unsigned WIN_FIX_STDCALL runWin(void *data);
659 FunctionPointer functionPointer;
663 void NativeThreadWrapper::start(FunctionPointer functionPointer, void *data)
665 this->functionPointer = functionPointer;
667 #if defined Q_OS_UNIX
668 const int state = pthread_create(&nativeThreadHandle, 0, NativeThreadWrapper::runUnix, this);
670 #elif defined(Q_OS_WINCE)
671 nativeThreadHandle = CreateThread(NULL, 0 , (LPTHREAD_START_ROUTINE)NativeThreadWrapper::runWin , this, 0, NULL);
672 #elif defined Q_OS_WIN
674 nativeThreadHandle = (Qt::HANDLE) _beginthreadex(NULL, 0, NativeThreadWrapper::runWin, this, 0, &thrdid);
678 void NativeThreadWrapper::startAndWait(FunctionPointer functionPointer, void *data)
680 QMutexLocker locker(&mutex);
681 start(functionPointer, data);
682 startCondition.wait(locker.mutex());
685 void NativeThreadWrapper::join()
687 #if defined Q_OS_UNIX
688 pthread_join(nativeThreadHandle, 0);
689 #elif defined Q_OS_WIN
690 WaitForSingleObject(nativeThreadHandle, INFINITE);
691 CloseHandle(nativeThreadHandle);
695 void *NativeThreadWrapper::runUnix(void *that)
697 NativeThreadWrapper *nativeThreadWrapper = reinterpret_cast<NativeThreadWrapper*>(that);
699 // Adopt thread, create QThread object.
700 nativeThreadWrapper->qthread = QThread::currentThread();
702 // Release main thread.
704 QMutexLocker lock(&nativeThreadWrapper->mutex);
705 nativeThreadWrapper->startCondition.wakeOne();
709 nativeThreadWrapper->functionPointer(nativeThreadWrapper->data);
713 QMutexLocker lock(&nativeThreadWrapper->mutex);
714 if (nativeThreadWrapper->waitForStop)
715 nativeThreadWrapper->stopCondition.wait(lock.mutex());
721 unsigned WIN_FIX_STDCALL NativeThreadWrapper::runWin(void *data)
727 void NativeThreadWrapper::stop()
729 QMutexLocker lock(&mutex);
731 stopCondition.wakeOne();
734 bool threadAdoptedOk = false;
736 void testNativeThreadAdoption(void *)
738 threadAdoptedOk = (QThread::currentThreadId() != 0
739 && QThread::currentThread() != 0
740 && QThread::currentThread() != mainThread);
742 void tst_QThread::nativeThreadAdoption()
744 threadAdoptedOk = false;
745 mainThread = QThread::currentThread();
746 NativeThreadWrapper nativeThread;
747 nativeThread.setWaitForStop();
748 nativeThread.startAndWait(testNativeThreadAdoption);
749 QVERIFY(nativeThread.qthread);
754 QVERIFY(threadAdoptedOk);
757 void adoptedThreadAffinityFunction(void *arg)
759 QThread **affinity = reinterpret_cast<QThread **>(arg);
760 QThread *current = QThread::currentThread();
761 affinity[0] = current;
762 affinity[1] = current->thread();
765 void tst_QThread::adoptedThreadAffinity()
767 QThread *affinity[2] = { 0, 0 };
769 NativeThreadWrapper thread;
770 thread.startAndWait(adoptedThreadAffinityFunction, affinity);
773 // adopted thread should have affinity to itself
774 QCOMPARE(affinity[0], affinity[1]);
777 void tst_QThread::adoptedThreadSetPriority()
780 NativeThreadWrapper nativeThread;
781 nativeThread.setWaitForStop();
782 nativeThread.startAndWait();
784 // change the priority of a running thread
785 QCOMPARE(nativeThread.qthread->priority(), QThread::InheritPriority);
786 nativeThread.qthread->setPriority(QThread::IdlePriority);
787 QCOMPARE(nativeThread.qthread->priority(), QThread::IdlePriority);
788 nativeThread.qthread->setPriority(QThread::LowestPriority);
789 QCOMPARE(nativeThread.qthread->priority(), QThread::LowestPriority);
790 nativeThread.qthread->setPriority(QThread::LowPriority);
791 QCOMPARE(nativeThread.qthread->priority(), QThread::LowPriority);
792 nativeThread.qthread->setPriority(QThread::NormalPriority);
793 QCOMPARE(nativeThread.qthread->priority(), QThread::NormalPriority);
794 nativeThread.qthread->setPriority(QThread::HighPriority);
795 QCOMPARE(nativeThread.qthread->priority(), QThread::HighPriority);
796 nativeThread.qthread->setPriority(QThread::HighestPriority);
797 QCOMPARE(nativeThread.qthread->priority(), QThread::HighestPriority);
798 nativeThread.qthread->setPriority(QThread::TimeCriticalPriority);
799 QCOMPARE(nativeThread.qthread->priority(), QThread::TimeCriticalPriority);
805 void tst_QThread::adoptedThreadExit()
807 NativeThreadWrapper nativeThread;
808 nativeThread.setWaitForStop();
810 nativeThread.startAndWait();
811 QVERIFY(nativeThread.qthread);
812 QVERIFY(nativeThread.qthread->isRunning());
813 QVERIFY(!nativeThread.qthread->isFinished());
819 void adoptedThreadExecFunction(void *)
821 QThread * const adoptedThread = QThread::currentThread();
822 QEventLoop eventLoop(adoptedThread);
826 o.thread = adoptedThread;
828 QTimer::singleShot(100, &o, SLOT(slot()));
830 const int result = eventLoop.exec();
831 QCOMPARE(result, code);
834 void tst_QThread::adoptedThreadExec()
836 NativeThreadWrapper nativeThread;
837 nativeThread.start(adoptedThreadExecFunction);
842 Test that you get the finished signal when an adopted thread exits.
844 void tst_QThread::adoptedThreadFinished()
846 NativeThreadWrapper nativeThread;
847 nativeThread.setWaitForStop();
848 nativeThread.startAndWait();
850 QObject::connect(nativeThread.qthread, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop()));
855 QTestEventLoop::instance().enterLoop(5);
856 QVERIFY(!QTestEventLoop::instance().timeout());
859 void tst_QThread::adoptedThreadExecFinished()
861 NativeThreadWrapper nativeThread;
862 nativeThread.setWaitForStop();
863 nativeThread.startAndWait(adoptedThreadExecFunction);
865 QObject::connect(nativeThread.qthread, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop()));
870 QTestEventLoop::instance().enterLoop(5);
871 QVERIFY(!QTestEventLoop::instance().timeout());
874 void tst_QThread::adoptMultipleThreads()
876 #if defined(Q_OS_WIN)
877 // Windows CE is not capable of handling that many threads. On the emulator it is dead with 26 threads already.
878 # if defined(Q_OS_WINCE)
879 const int numThreads = 20;
881 // need to test lots of threads, so that we exceed MAXIMUM_WAIT_OBJECTS in qt_adopted_thread_watcher()
882 const int numThreads = 200;
885 const int numThreads = 5;
887 QVector<NativeThreadWrapper*> nativeThreads;
889 SignalRecorder recorder;
891 for (int i = 0; i < numThreads; ++i) {
892 nativeThreads.append(new NativeThreadWrapper());
893 nativeThreads.at(i)->setWaitForStop();
894 nativeThreads.at(i)->startAndWait();
895 QObject::connect(nativeThreads.at(i)->qthread, SIGNAL(finished()), &recorder, SLOT(slot()));
898 QObject::connect(nativeThreads.at(numThreads - 1)->qthread, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop()));
900 for (int i = 0; i < numThreads; ++i) {
901 nativeThreads.at(i)->stop();
902 nativeThreads.at(i)->join();
903 delete nativeThreads.at(i);
906 QTestEventLoop::instance().enterLoop(5);
907 QVERIFY(!QTestEventLoop::instance().timeout());
908 QCOMPARE(recorder.activationCount.load(), numThreads);
911 void tst_QThread::adoptMultipleThreadsOverlap()
913 #if defined(Q_OS_WIN)
914 // Windows CE is not capable of handling that many threads. On the emulator it is dead with 26 threads already.
915 # if defined(Q_OS_WINCE)
916 const int numThreads = 20;
918 // need to test lots of threads, so that we exceed MAXIMUM_WAIT_OBJECTS in qt_adopted_thread_watcher()
919 const int numThreads = 200;
922 const int numThreads = 5;
924 QVector<NativeThreadWrapper*> nativeThreads;
926 SignalRecorder recorder;
928 for (int i = 0; i < numThreads; ++i) {
929 nativeThreads.append(new NativeThreadWrapper());
930 nativeThreads.at(i)->setWaitForStop();
931 nativeThreads.at(i)->mutex.lock();
932 nativeThreads.at(i)->start();
934 for (int i = 0; i < numThreads; ++i) {
935 nativeThreads.at(i)->startCondition.wait(&nativeThreads.at(i)->mutex);
936 QObject::connect(nativeThreads.at(i)->qthread, SIGNAL(finished()), &recorder, SLOT(slot()));
937 nativeThreads.at(i)->mutex.unlock();
940 QObject::connect(nativeThreads.at(numThreads - 1)->qthread, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop()));
942 for (int i = 0; i < numThreads; ++i) {
943 nativeThreads.at(i)->stop();
944 nativeThreads.at(i)->join();
945 delete nativeThreads.at(i);
948 QTestEventLoop::instance().enterLoop(5);
949 QVERIFY(!QTestEventLoop::instance().timeout());
950 QCOMPARE(recorder.activationCount.load(), numThreads);
952 void tst_QThread::stressTest()
954 #if defined(Q_OS_WINCE)
955 QSKIP("Disconnects on WinCE, skipping...");
959 while (t.elapsed() < one_minute) {
966 class Syncronizer : public QObject
969 void setProp(int p) {
976 void propChanged(int);
978 Syncronizer() : m_prop(42) {}
982 void tst_QThread::exitAndStart()
985 thread.exit(555); //should do nothing
989 //test that the thread is running by executing queued connected signal there
991 sync1.moveToThread(&thread);
993 sync2.moveToThread(&thread);
994 connect(&sync2, SIGNAL(propChanged(int)), &sync1, SLOT(setProp(int)), Qt::QueuedConnection);
995 connect(&sync1, SIGNAL(propChanged(int)), &thread, SLOT(quit()), Qt::QueuedConnection);
996 QMetaObject::invokeMethod(&sync2, "setProp", Qt::QueuedConnection , Q_ARG(int, 89));
998 while(!thread.wait(10))
1000 QCOMPARE(sync2.m_prop, 89);
1001 QCOMPARE(sync1.m_prop, 89);
1004 void tst_QThread::exitAndExec()
1006 class Thread : public QThread {
1013 value = exec(); //First entrence
1015 value = exec(); // Second loop
1022 thread.sem1.release(); //should exit the first loop
1023 thread.sem2.acquire();
1024 int v = thread.value;
1027 //test that the thread is running by executing queued connected signal there
1029 sync1.moveToThread(&thread);
1031 sync2.moveToThread(&thread);
1032 connect(&sync2, SIGNAL(propChanged(int)), &sync1, SLOT(setProp(int)), Qt::QueuedConnection);
1033 connect(&sync1, SIGNAL(propChanged(int)), &thread, SLOT(quit()), Qt::QueuedConnection);
1034 QMetaObject::invokeMethod(&sync2, "setProp", Qt::QueuedConnection , Q_ARG(int, 89));
1036 while(!thread.wait(10))
1038 QCOMPARE(sync2.m_prop, 89);
1039 QCOMPARE(sync1.m_prop, 89);
1042 void tst_QThread::connectThreadFinishedSignalToObjectDeleteLaterSlot()
1045 QObject *object = new QObject;
1046 QPointer<QObject> p = object;
1047 QVERIFY(!p.isNull());
1048 connect(&thread, SIGNAL(started()), &thread, SLOT(quit()), Qt::DirectConnection);
1049 connect(&thread, SIGNAL(finished()), object, SLOT(deleteLater()));
1050 object->moveToThread(&thread);
1052 QVERIFY(thread.wait(30000));
1053 QVERIFY(p.isNull());
1056 class Waiting_Thread : public QThread
1059 enum { WaitTime = 800 };
1061 QWaitCondition cond1;
1062 QWaitCondition cond2;
1066 QMutexLocker locker(&mutex);
1068 cond2.wait(&mutex, WaitTime);
1072 void tst_QThread::wait2()
1074 QElapsedTimer timer;
1075 Waiting_Thread thread;
1078 QVERIFY(!thread.wait(Waiting_Thread::WaitTime));
1079 qint64 elapsed = timer.elapsed(); // On Windows, we sometimes get (WaitTime - 1).
1080 QVERIFY2(elapsed >= Waiting_Thread::WaitTime - 1, qPrintable(QString::fromLatin1("elapsed: %1").arg(elapsed)));
1083 thread.cond1.wakeOne();
1084 QVERIFY(thread.wait(/*Waiting_Thread::WaitTime * 1.4*/));
1085 elapsed = timer.elapsed();
1086 QVERIFY2(elapsed - Waiting_Thread::WaitTime >= -1, qPrintable(QString::fromLatin1("elapsed: %1").arg(elapsed)));
1090 class SlowSlotObject : public QObject {
1094 QWaitCondition cond;
1097 QMutexLocker locker(&mutex);
1102 void tst_QThread::wait3_slowDestructor()
1104 SlowSlotObject slow;
1106 QObject::connect(&thread, SIGNAL(finished()), &slow, SLOT(slowSlot()), Qt::DirectConnection);
1108 enum { WaitTime = 1800 };
1109 QElapsedTimer timer;
1113 //the quit function will cause the thread to finish and enter the slowSlot that is blocking
1116 QVERIFY(!thread.wait(Waiting_Thread::WaitTime));
1117 qint64 elapsed = timer.elapsed();
1118 QVERIFY2(elapsed >= Waiting_Thread::WaitTime - 1, qPrintable(QString::fromLatin1("elapsed: %1").arg(elapsed)));
1120 slow.cond.wakeOne();
1121 //now the thread should finish quickly
1122 QVERIFY(thread.wait(one_minute));
1125 void tst_QThread::destroyFinishRace()
1127 class Thread : public QThread { void run() {} };
1128 for (int i = 0; i < 15; i++) {
1129 Thread *thr = new Thread;
1130 connect(thr, SIGNAL(finished()), thr, SLOT(deleteLater()));
1131 QPointer<QThread> weak(static_cast<QThread*>(thr));
1134 qApp->processEvents();
1135 qApp->processEvents();
1136 qApp->processEvents();
1137 qApp->processEvents();
1142 void tst_QThread::startFinishRace()
1144 class Thread : public QThread {
1146 Thread() : i (50) {}
1149 if (!i) disconnect(this, SIGNAL(finished()), 0, 0);
1153 for (int i = 0; i < 15; i++) {
1155 connect(&thr, SIGNAL(finished()), &thr, SLOT(start()));
1157 while (!thr.isFinished() || thr.i != 0) {
1158 qApp->processEvents();
1159 qApp->processEvents();
1160 qApp->processEvents();
1161 qApp->processEvents();
1167 void tst_QThread::startAndQuitCustomEventLoop()
1169 struct Thread : QThread {
1170 void run() { QEventLoop().exec(); }
1173 for (int i = 0; i < 5; i++) {
1181 class FinishedTestObject : public QObject {
1184 FinishedTestObject() : ok(false) {}
1187 void slotFinished() {
1188 QThread *t = qobject_cast<QThread *>(sender());
1189 ok = t && t->isFinished() && !t->isRunning();
1193 void tst_QThread::isRunningInFinished()
1195 for (int i = 0; i < 15; i++) {
1198 FinishedTestObject localObject;
1199 FinishedTestObject inThreadObject;
1200 localObject.setObjectName("...");
1201 inThreadObject.moveToThread(&thread);
1202 connect(&thread, SIGNAL(finished()), &localObject, SLOT(slotFinished()));
1203 connect(&thread, SIGNAL(finished()), &inThreadObject, SLOT(slotFinished()));
1205 connect(&thread, SIGNAL(finished()), &loop, SLOT(quit()));
1206 QMetaObject::invokeMethod(&thread, "quit", Qt::QueuedConnection);
1208 QVERIFY(!thread.isRunning());
1209 QVERIFY(thread.isFinished());
1210 QVERIFY(localObject.ok);
1211 QVERIFY(inThreadObject.ok);
1216 Q_CORE_EXPORT uint qGlobalPostedEventsCount();
1219 class DummyEventDispatcher : public QAbstractEventDispatcher {
1221 DummyEventDispatcher() : QAbstractEventDispatcher(), visited(false) {}
1222 bool processEvents(QEventLoop::ProcessEventsFlags) {
1225 QCoreApplication::sendPostedEvents();
1228 bool hasPendingEvents() {
1229 return qGlobalPostedEventsCount();
1231 void registerSocketNotifier(QSocketNotifier *) {}
1232 void unregisterSocketNotifier(QSocketNotifier *) {}
1233 void registerTimer(int, int, Qt::TimerType, QObject *) {}
1234 bool unregisterTimer(int ) { return false; }
1235 bool unregisterTimers(QObject *) { return false; }
1236 QList<TimerInfo> registeredTimers(QObject *) const { return QList<TimerInfo>(); }
1237 int remainingTime(int) { return 0; }
1243 bool registerEventNotifier(QWinEventNotifier *) { return false; }
1244 void unregisterEventNotifier(QWinEventNotifier *) { }
1250 class ThreadObj : public QObject
1261 void tst_QThread::customEventDispatcher()
1264 // there should be no ED yet
1265 QVERIFY(!thr.eventDispatcher());
1266 DummyEventDispatcher *ed = new DummyEventDispatcher;
1267 thr.setEventDispatcher(ed);
1268 // the new ED should be set
1269 QCOMPARE(thr.eventDispatcher(), ed);
1270 // test the alternative API of QAbstractEventDispatcher
1271 QCOMPARE(QAbstractEventDispatcher::instance(&thr), ed);
1273 // start() should not overwrite the ED
1274 QCOMPARE(thr.eventDispatcher(), ed);
1277 obj.moveToThread(&thr);
1278 // move was successful?
1279 QCOMPARE(obj.thread(), &thr);
1281 connect(&obj, SIGNAL(visited()), &loop, SLOT(quit()), Qt::QueuedConnection);
1282 QMetaObject::invokeMethod(&obj, "visit", Qt::QueuedConnection);
1284 // test that the ED has really been used
1285 QVERIFY(ed->visited);
1287 QPointer<DummyEventDispatcher> weak_ed(ed);
1288 QVERIFY(!weak_ed.isNull());
1290 // wait for thread to be stopped
1291 QVERIFY(thr.wait(30000));
1292 // test that ED has been deleted
1293 QVERIFY(weak_ed.isNull());
1296 class Job : public QObject
1300 Job(QThread *thread, int deleteDelay, QObject *parent = 0)
1301 : QObject(parent), quitLocker(thread), exitThreadCalled(false)
1303 moveToThread(thread);
1304 QTimer::singleShot(deleteDelay, this, SLOT(deleteLater()));
1305 QTimer::singleShot(1000, this, SLOT(exitThread()));
1311 exitThreadCalled = true;
1316 QEventLoopLocker quitLocker;
1318 bool exitThreadCalled;
1321 void tst_QThread::quitLock()
1326 connect(&thread, SIGNAL(finished()), &loop, SLOT(quit()));
1331 job = new Job(&thread, 500);
1332 QCOMPARE(job->thread(), &thread);
1334 QVERIFY(!job->exitThreadCalled);
1337 job = new Job(&thread, 2500);
1338 QCOMPARE(job->thread(), &thread);
1340 QVERIFY(job->exitThreadCalled);
1343 QTEST_MAIN(tst_QThread)
1344 #include "tst_qthread.moc"