summaryrefslogtreecommitdiffstats
path: root/tests/auto/corelib/concurrent/qthreadpool/tst_qthreadpool.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'tests/auto/corelib/concurrent/qthreadpool/tst_qthreadpool.cpp')
-rw-r--r--tests/auto/corelib/concurrent/qthreadpool/tst_qthreadpool.cpp849
1 files changed, 0 insertions, 849 deletions
diff --git a/tests/auto/corelib/concurrent/qthreadpool/tst_qthreadpool.cpp b/tests/auto/corelib/concurrent/qthreadpool/tst_qthreadpool.cpp
deleted file mode 100644
index 1dd0410f41..0000000000
--- a/tests/auto/corelib/concurrent/qthreadpool/tst_qthreadpool.cpp
+++ /dev/null
@@ -1,849 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/
-**
-** 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 <qdatetime.h>
-#include <qthreadpool.h>
-#include <qstring.h>
-#include <qmutex.h>
-
-typedef void (*FunctionPointer)();
-
-class FunctionPointerTask : public QRunnable
-{
-public:
- FunctionPointerTask(FunctionPointer function)
- :function(function) {}
- void run() { function(); }
-private:
- FunctionPointer function;
-};
-
-QRunnable *createTask(FunctionPointer pointer)
-{
- return new FunctionPointerTask(pointer);
-}
-
-class tst_QThreadPool : public QObject
-{
- Q_OBJECT
-private slots:
- void runFunction();
- void createThreadRunFunction();
- void runMultiple();
- void waitcomplete();
- void runTask();
- void singleton();
- void destruction();
- void threadRecycling();
- void expiryTimeout();
-#ifndef QT_NO_EXCEPTIONS
- void exceptions();
-#endif
- void setMaxThreadCount_data();
- void setMaxThreadCount();
- void setMaxThreadCountStartsAndStopsThreads();
- void reserveThread_data();
- void reserveThread();
- void releaseThread_data();
- void releaseThread();
- void start();
- void tryStart();
- void tryStartPeakThreadCount();
- void tryStartCount();
- void waitForDone();
- void waitForDoneTimeout();
- void destroyingWaitsForTasksToFinish();
- void stressTest();
-};
-
-int testFunctionCount;
-
-void sleepTestFunction()
-{
- QTest::qSleep(1000);
- ++testFunctionCount;
-}
-
-void emptyFunct()
-{
-
-}
-
-void noSleepTestFunction()
-{
- ++testFunctionCount;
-}
-
-void sleepTestFunctionMutex()
-{
- static QMutex testMutex;
- QTest::qSleep(1000);
- testMutex.lock();
- ++testFunctionCount;
- testMutex.unlock();
-}
-
-void noSleepTestFunctionMutex()
-{
- static QMutex testMutex;
- testMutex.lock();
- ++testFunctionCount;
- testMutex.unlock();
-}
-
-void tst_QThreadPool::runFunction()
-{
- {
- QThreadPool manager;
- testFunctionCount = 0;
- manager.start(createTask(noSleepTestFunction));
- }
- QCOMPARE(testFunctionCount, 1);
-}
-
-void tst_QThreadPool::createThreadRunFunction()
-{
- {
- QThreadPool manager;
- testFunctionCount = 0;
- manager.start(createTask(noSleepTestFunction));
- }
-
- QCOMPARE(testFunctionCount, 1);
-}
-
-void tst_QThreadPool::runMultiple()
-{
- const int runs = 10;
-
- {
- QThreadPool manager;
- testFunctionCount = 0;
- for (int i = 0; i < runs; ++i) {
- manager.start(createTask(sleepTestFunctionMutex));
- }
- }
- QCOMPARE(testFunctionCount, runs);
-
- {
- QThreadPool manager;
- testFunctionCount = 0;
- for (int i = 0; i < runs; ++i) {
- manager.start(createTask(noSleepTestFunctionMutex));
- }
- }
- QCOMPARE(testFunctionCount, runs);
-
- {
- QThreadPool manager;
- for (int i = 0; i < 500; ++i)
- manager.start(createTask(emptyFunct));
- }
-}
-
-void tst_QThreadPool::waitcomplete()
-{
- testFunctionCount = 0;
- const int runs = 500;
- for (int i = 0; i < 500; ++i) {
- QThreadPool pool;
- pool.start(createTask(noSleepTestFunction));
- }
- QCOMPARE(testFunctionCount, runs);
-}
-
-volatile bool ran;
-class TestTask : public QRunnable
-{
-public:
- void run()
- {
- ran = true;
- }
-};
-
-void tst_QThreadPool::runTask()
-{
- QThreadPool manager;
- ran = false;
- manager.start(new TestTask());
- QTRY_VERIFY(ran);
-}
-
-/*
- Test running via QThreadPool::globalInstance()
-*/
-void tst_QThreadPool::singleton()
-{
- ran = false;
- QThreadPool::globalInstance()->start(new TestTask());
- QTRY_VERIFY(ran);
-}
-
-int *value = 0;
-class IntAccessor : public QRunnable
-{
-public:
- void run()
- {
- for (int i = 0; i < 100; ++i) {
- ++(*value);
- QTest::qSleep(1);
- }
- }
-};
-
-/*
- Test that the ThreadManager destructor waits until
- all threads have completed.
-*/
-void tst_QThreadPool::destruction()
-{
- value = new int;
- QThreadPool *threadManager = new QThreadPool();
- threadManager->start(new IntAccessor());
- threadManager->start(new IntAccessor());
- delete threadManager;
- delete value;
- value = 0;
-}
-
-QSemaphore threadRecyclingSemaphore;
-QThread *recycledThread = 0;
-
-class ThreadRecorderTask : public QRunnable
-{
-public:
- void run()
- {
- recycledThread = QThread::currentThread();
- threadRecyclingSemaphore.release();
- }
-};
-
-/*
- Test that the thread pool really reuses threads.
-*/
-void tst_QThreadPool::threadRecycling()
-{
- QThreadPool threadPool;
-
- threadPool.start(new ThreadRecorderTask());
- threadRecyclingSemaphore.acquire();
- QThread *thread1 = recycledThread;
-
- QTest::qSleep(100);
-
- threadPool.start(new ThreadRecorderTask());
- threadRecyclingSemaphore.acquire();
- QThread *thread2 = recycledThread;
- QCOMPARE(thread1, thread2);
-
- QTest::qSleep(100);
-
- threadPool.start(new ThreadRecorderTask());
- threadRecyclingSemaphore.acquire();
- QThread *thread3 = recycledThread;
- QCOMPARE(thread2, thread3);
-}
-
-class ExpiryTimeoutTask : public QRunnable
-{
-public:
- QThread *thread;
- int runCount;
- QSemaphore semaphore;
-
- ExpiryTimeoutTask()
- : thread(0), runCount(0)
- {
- setAutoDelete(false);
- }
-
- void run()
- {
- thread = QThread::currentThread();
- ++runCount;
- semaphore.release();
- }
-};
-
-void tst_QThreadPool::expiryTimeout()
-{
- ExpiryTimeoutTask task;
-
- QThreadPool threadPool;
- threadPool.setMaxThreadCount(1);
-
- int expiryTimeout = threadPool.expiryTimeout();
- threadPool.setExpiryTimeout(1000);
- QCOMPARE(threadPool.expiryTimeout(), 1000);
-
- // run the task
- threadPool.start(&task);
- QVERIFY(task.semaphore.tryAcquire(1, 10000));
- QCOMPARE(task.runCount, 1);
- QVERIFY(!task.thread->wait(100));
- // thread should expire
- QThread *firstThread = task.thread;
- QVERIFY(task.thread->wait(10000));
-
- // run task again, thread should be restarted
- threadPool.start(&task);
- QVERIFY(task.semaphore.tryAcquire(1, 10000));
- QCOMPARE(task.runCount, 2);
- QVERIFY(!task.thread->wait(100));
- // thread should expire again
- QVERIFY(task.thread->wait(10000));
-
- // thread pool should have reused the expired thread (instead of
- // starting a new one)
- QCOMPARE(firstThread, task.thread);
-
- threadPool.setExpiryTimeout(expiryTimeout);
- QCOMPARE(threadPool.expiryTimeout(), expiryTimeout);
-}
-
-#ifndef QT_NO_EXCEPTIONS
-class ExceptionTask : public QRunnable
-{
-public:
- void run()
- {
- throw new int;
- }
-};
-
-void tst_QThreadPool::exceptions()
-{
- ExceptionTask task;
- {
- QThreadPool threadPool;
-// Uncomment this for a nice crash.
-// threadPool.start(&task);
- }
-}
-#endif
-
-void tst_QThreadPool::setMaxThreadCount_data()
-{
- QTest::addColumn<int>("limit");
-
- QTest::newRow("") << 1;
- QTest::newRow("") << -1;
- QTest::newRow("") << 2;
- QTest::newRow("") << -2;
- QTest::newRow("") << 4;
- QTest::newRow("") << -4;
- QTest::newRow("") << 0;
- QTest::newRow("") << 12345;
- QTest::newRow("") << -6789;
- QTest::newRow("") << 42;
- QTest::newRow("") << -666;
-}
-
-void tst_QThreadPool::setMaxThreadCount()
-{
- QFETCH(int, limit);
- QThreadPool *threadPool = QThreadPool::globalInstance();
- int savedLimit = threadPool->maxThreadCount();
-
- // maxThreadCount() should always return the previous argument to
- // setMaxThreadCount(), regardless of input
- threadPool->setMaxThreadCount(limit);
- QCOMPARE(threadPool->maxThreadCount(), limit);
-
- // the value returned from maxThreadCount() should always be valid input for setMaxThreadCount()
- threadPool->setMaxThreadCount(savedLimit);
- QCOMPARE(threadPool->maxThreadCount(), savedLimit);
-
- // setting the limit on children should have no effect on the parent
- {
- QThreadPool threadPool2(threadPool);
- savedLimit = threadPool2.maxThreadCount();
-
- // maxThreadCount() should always return the previous argument to
- // setMaxThreadCount(), regardless of input
- threadPool2.setMaxThreadCount(limit);
- QCOMPARE(threadPool2.maxThreadCount(), limit);
-
- // the value returned from maxThreadCount() should always be valid input for setMaxThreadCount()
- threadPool2.setMaxThreadCount(savedLimit);
- QCOMPARE(threadPool2.maxThreadCount(), savedLimit);
- }
-}
-
-void tst_QThreadPool::setMaxThreadCountStartsAndStopsThreads()
-{
- class WaitingTask : public QRunnable
- {
- public:
- QSemaphore waitForStarted, waitToFinish;
-
- WaitingTask() { setAutoDelete(false); }
-
- void run()
- {
- waitForStarted.release();
- waitToFinish.acquire();
- }
- };
-
- QThreadPool threadPool;
- threadPool.setMaxThreadCount(1);
-
- WaitingTask *task = new WaitingTask;
- threadPool.start(task);
- QVERIFY(task->waitForStarted.tryAcquire(1, 1000));
-
- // thread limit is 1, cannot start more tasks
- threadPool.start(task);
- QVERIFY(!task->waitForStarted.tryAcquire(1, 1000));
-
- // increasing the limit by 1 should start the task immediately
- threadPool.setMaxThreadCount(2);
- QVERIFY(task->waitForStarted.tryAcquire(1, 1000));
-
- // ... but we still cannot start more tasks
- threadPool.start(task);
- QVERIFY(!task->waitForStarted.tryAcquire(1, 1000));
-
- // increasing the limit should be able to start more than one at a time
- threadPool.start(task);
- threadPool.setMaxThreadCount(4);
- QVERIFY(task->waitForStarted.tryAcquire(2, 1000));
-
- // ... but we still cannot start more tasks
- threadPool.start(task);
- threadPool.start(task);
- QVERIFY(!task->waitForStarted.tryAcquire(2, 1000));
-
- // decreasing the thread limit should cause the active thread count to go down
- threadPool.setMaxThreadCount(2);
- QCOMPARE(threadPool.activeThreadCount(), 4);
- task->waitToFinish.release(2);
- QTest::qWait(1000);
- QCOMPARE(threadPool.activeThreadCount(), 2);
-
- // ... and we still cannot start more tasks
- threadPool.start(task);
- threadPool.start(task);
- QVERIFY(!task->waitForStarted.tryAcquire(2, 1000));
-
- // start all remaining tasks
- threadPool.start(task);
- threadPool.start(task);
- threadPool.start(task);
- threadPool.start(task);
- threadPool.setMaxThreadCount(8);
- QVERIFY(task->waitForStarted.tryAcquire(6, 1000));
-
- task->waitToFinish.release(10);
-// delete task;
-}
-
-void tst_QThreadPool::reserveThread_data()
-{
- setMaxThreadCount_data();
-}
-
-void tst_QThreadPool::reserveThread()
-{
- QFETCH(int, limit);
- QThreadPool *threadpool = QThreadPool::globalInstance();
- int savedLimit = threadpool->maxThreadCount();
- threadpool->setMaxThreadCount(limit);
-
- // reserve up to the limit
- for (int i = 0; i < limit; ++i)
- threadpool->reserveThread();
-
- // reserveThread() should always reserve a thread, regardless of
- // how many have been previously reserved
- threadpool->reserveThread();
- QCOMPARE(threadpool->activeThreadCount(), (limit > 0 ? limit : 0) + 1);
- threadpool->reserveThread();
- QCOMPARE(threadpool->activeThreadCount(), (limit > 0 ? limit : 0) + 2);
-
- // cleanup
- threadpool->releaseThread();
- threadpool->releaseThread();
- for (int i = 0; i < limit; ++i)
- threadpool->releaseThread();
-
- // reserving threads in children should not effect the parent
- {
- QThreadPool threadpool2(threadpool);
- threadpool2.setMaxThreadCount(limit);
-
- // reserve up to the limit
- for (int i = 0; i < limit; ++i)
- threadpool2.reserveThread();
-
- // reserveThread() should always reserve a thread, regardless
- // of how many have been previously reserved
- threadpool2.reserveThread();
- QCOMPARE(threadpool2.activeThreadCount(), (limit > 0 ? limit : 0) + 1);
- threadpool2.reserveThread();
- QCOMPARE(threadpool2.activeThreadCount(), (limit > 0 ? limit : 0) + 2);
-
- threadpool->reserveThread();
- QCOMPARE(threadpool->activeThreadCount(), 1);
- threadpool->reserveThread();
- QCOMPARE(threadpool->activeThreadCount(), 2);
-
- // cleanup
- threadpool2.releaseThread();
- threadpool2.releaseThread();
- threadpool->releaseThread();
- threadpool->releaseThread();
- while (threadpool2.activeThreadCount() > 0)
- threadpool2.releaseThread();
- }
-
- // reset limit on global QThreadPool
- threadpool->setMaxThreadCount(savedLimit);
-}
-
-void tst_QThreadPool::releaseThread_data()
-{
- setMaxThreadCount_data();
-}
-
-void tst_QThreadPool::releaseThread()
-{
- QFETCH(int, limit);
- QThreadPool *threadpool = QThreadPool::globalInstance();
- int savedLimit = threadpool->maxThreadCount();
- threadpool->setMaxThreadCount(limit);
-
- // reserve up to the limit
- for (int i = 0; i < limit; ++i)
- threadpool->reserveThread();
-
- // release should decrease the number of reserved threads
- int reserved = threadpool->activeThreadCount();
- while (reserved-- > 0) {
- threadpool->releaseThread();
- QCOMPARE(threadpool->activeThreadCount(), reserved);
- }
- QCOMPARE(threadpool->activeThreadCount(), 0);
-
- // releaseThread() can release more than have been reserved
- threadpool->releaseThread();
- QCOMPARE(threadpool->activeThreadCount(), -1);
- threadpool->reserveThread();
- QCOMPARE(threadpool->activeThreadCount(), 0);
-
- // releasing threads in children should not effect the parent
- {
- QThreadPool threadpool2(threadpool);
- threadpool2.setMaxThreadCount(limit);
-
- // reserve up to the limit
- for (int i = 0; i < limit; ++i)
- threadpool2.reserveThread();
-
- // release should decrease the number of reserved threads
- int reserved = threadpool2.activeThreadCount();
- while (reserved-- > 0) {
- threadpool2.releaseThread();
- QCOMPARE(threadpool2.activeThreadCount(), reserved);
- QCOMPARE(threadpool->activeThreadCount(), 0);
- }
- QCOMPARE(threadpool2.activeThreadCount(), 0);
- QCOMPARE(threadpool->activeThreadCount(), 0);
-
- // releaseThread() can release more than have been reserved
- threadpool2.releaseThread();
- QCOMPARE(threadpool2.activeThreadCount(), -1);
- QCOMPARE(threadpool->activeThreadCount(), 0);
- threadpool2.reserveThread();
- QCOMPARE(threadpool2.activeThreadCount(), 0);
- QCOMPARE(threadpool->activeThreadCount(), 0);
- }
-
- // reset limit on global QThreadPool
- threadpool->setMaxThreadCount(savedLimit);
-}
-
-QAtomicInt count;
-class CountingRunnable : public QRunnable
-{
- public: void run()
- {
- count.ref();
- }
-};
-
-void tst_QThreadPool::start()
-{
- const int runs = 1000;
- count.store(0);
- {
- QThreadPool threadPool;
- for (int i = 0; i< runs; ++i) {
- threadPool.start(new CountingRunnable());
- }
- }
- QCOMPARE(count.load(), runs);
-}
-
-void tst_QThreadPool::tryStart()
-{
- class WaitingTask : public QRunnable
- {
- public:
- QSemaphore semaphore;
-
- WaitingTask() { setAutoDelete(false); }
-
- void run()
- {
- semaphore.acquire();
- count.ref();
- }
- };
-
- count.store(0);
-
- WaitingTask task;
- QThreadPool threadPool;
- for (int i = 0; i < threadPool.maxThreadCount(); ++i) {
- threadPool.start(&task);
- }
- QVERIFY(!threadPool.tryStart(&task));
- task.semaphore.release(threadPool.maxThreadCount());
- threadPool.waitForDone();
- QCOMPARE(count.load(), threadPool.maxThreadCount());
-}
-
-QMutex mutex;
-int activeThreads = 0;
-int peakActiveThreads = 0;
-void tst_QThreadPool::tryStartPeakThreadCount()
-{
- class CounterTask : public QRunnable
- {
- public:
- CounterTask() { setAutoDelete(false); }
-
- void run()
- {
- {
- QMutexLocker lock(&mutex);
- ++activeThreads;
- peakActiveThreads = qMax(peakActiveThreads, activeThreads);
- }
-
- QTest::qWait(100);
- {
- QMutexLocker lock(&mutex);
- --activeThreads;
- }
- }
- };
-
- CounterTask task;
- QThreadPool threadPool;
-
- for (int i = 0; i < 20; ++i) {
- if (threadPool.tryStart(&task) == false)
- QTest::qWait(10);
- }
- QCOMPARE(peakActiveThreads, QThread::idealThreadCount());
-
- for (int i = 0; i < 20; ++i) {
- if (threadPool.tryStart(&task) == false)
- QTest::qWait(10);
- }
- QCOMPARE(peakActiveThreads, QThread::idealThreadCount());
-}
-
-void tst_QThreadPool::tryStartCount()
-{
- class SleeperTask : public QRunnable
- {
- public:
- SleeperTask() { setAutoDelete(false); }
-
- void run()
- {
- QTest::qWait(50);
- }
- };
-
- SleeperTask task;
- QThreadPool threadPool;
- const int runs = 5;
-
- for (int i = 0; i < runs; ++i) {
- int count = 0;
- while (threadPool.tryStart(&task))
- ++count;
- QCOMPARE(count, QThread::idealThreadCount());
-
- QTest::qWait(100);
- }
-}
-
-void tst_QThreadPool::waitForDone()
-{
- QTime total, pass;
- total.start();
-
- QThreadPool threadPool;
- while (total.elapsed() < 10000) {
- int runs;
- count.store(runs = 0);
- pass.restart();
- while (pass.elapsed() < 100) {
- threadPool.start(new CountingRunnable());
- ++runs;
- }
- threadPool.waitForDone();
- QCOMPARE(count.load(), runs);
-
- count.store(runs = 0);
- pass.restart();
- while (pass.elapsed() < 100) {
- threadPool.start(new CountingRunnable());
- threadPool.start(new CountingRunnable());
- runs += 2;
- }
- threadPool.waitForDone();
- QCOMPARE(count.load(), runs);
- }
-}
-
-void tst_QThreadPool::waitForDoneTimeout()
-{
- class BlockedTask : public QRunnable
- {
- public:
- QMutex mutex;
- BlockedTask() { setAutoDelete(false); }
-
- void run()
- {
- mutex.lock();
- mutex.unlock();
- QTest::qSleep(50);
- }
- };
-
- QThreadPool threadPool;
-
- BlockedTask *task = new BlockedTask;
- task->mutex.lock();
- threadPool.start(task);
- QVERIFY(!threadPool.waitForDone(100));
- task->mutex.unlock();
- QVERIFY(threadPool.waitForDone(400));
-}
-
-void tst_QThreadPool::destroyingWaitsForTasksToFinish()
-{
- QTime total, pass;
- total.start();
-
- while (total.elapsed() < 10000) {
- int runs;
- count.store(runs = 0);
- {
- QThreadPool threadPool;
- pass.restart();
- while (pass.elapsed() < 100) {
- threadPool.start(new CountingRunnable());
- ++runs;
- }
- }
- QCOMPARE(count.load(), runs);
-
- count.store(runs = 0);
- {
- QThreadPool threadPool;
- pass.restart();
- while (pass.elapsed() < 100) {
- threadPool.start(new CountingRunnable());
- threadPool.start(new CountingRunnable());
- runs += 2;
- }
- }
- QCOMPARE(count.load(), runs);
- }
-}
-
-void tst_QThreadPool::stressTest()
-{
- class Task : public QRunnable
- {
- QSemaphore semaphore;
- public:
- Task() { setAutoDelete(false); }
-
- void start()
- {
- QThreadPool::globalInstance()->start(this);
- }
-
- void wait()
- {
- semaphore.acquire();
- }
-
- void run()
- {
- semaphore.release();
- }
- };
-
- QTime total;
- total.start();
- while (total.elapsed() < 30000) {
- Task t;
- t.start();
- t.wait();
- }
-}
-
-QTEST_MAIN(tst_QThreadPool);
-#include "tst_qthreadpool.moc"