From 0d8ba7e34974fe9c1a60977a10d34413650b33b0 Mon Sep 17 00:00:00 2001 From: Corentin Jabot Date: Sat, 27 Jul 2013 23:02:48 +0200 Subject: [PATCH] QThreadPool - Add method clear() to remove queued QRunnable. QThreadPool::clear() method removes all queued QRunnable. When a large number of long-running tasks are queud in a QThreadPool its destruction, which calls waitForDone(), can be quite long. QThreadPool:clear() removes (and deletes when appropriate) all QRunnable that have yet to be started from the queue enabling a faster interruption. Change-Id: Ie5d6028ad3cfe7e439d1db068c8d0936ff818db9 Reviewed-by: David Faure --- src/corelib/thread/qthreadpool.cpp | 27 +++++++++++++++++ src/corelib/thread/qthreadpool.h | 2 ++ src/corelib/thread/qthreadpool_p.h | 1 + .../thread/qthreadpool/tst_qthreadpool.cpp | 29 +++++++++++++++++++ 4 files changed, 59 insertions(+) diff --git a/src/corelib/thread/qthreadpool.cpp b/src/corelib/thread/qthreadpool.cpp index a7d52f9652..bee6790705 100644 --- a/src/corelib/thread/qthreadpool.cpp +++ b/src/corelib/thread/qthreadpool.cpp @@ -308,6 +308,18 @@ bool QThreadPoolPrivate::waitForDone(int msecs) return queue.isEmpty() && activeThreads == 0; } +void QThreadPoolPrivate::clear() +{ + QMutexLocker locker(&mutex); + for (QList >::const_iterator it = queue.constBegin(); + it != queue.constEnd(); ++it) { + QRunnable* r = it->first; + if (r->autoDelete() && !--r->ref) + delete r; + } + queue.clear(); +} + /*! \internal Seaches for \a runnable in the queue, removes it from the queue and @@ -609,6 +621,21 @@ bool QThreadPool::waitForDone(int msecs) return rc; } +/*! + \since 5.2 + + Removes the runnables that are not yet started from the queue. + The runnables for which \l{QRunnable::autoDelete()}{runnable->autoDelete()} + returns true are deleted. + + \sa start() +*/ +void QThreadPool::clear() +{ + Q_D(QThreadPool); + d->clear(); +} + QT_END_NAMESPACE #endif diff --git a/src/corelib/thread/qthreadpool.h b/src/corelib/thread/qthreadpool.h index ffc16dedbe..22a42c2272 100644 --- a/src/corelib/thread/qthreadpool.h +++ b/src/corelib/thread/qthreadpool.h @@ -83,6 +83,8 @@ public: void releaseThread(); bool waitForDone(int msecs = -1); + + void clear(); }; QT_END_NAMESPACE diff --git a/src/corelib/thread/qthreadpool_p.h b/src/corelib/thread/qthreadpool_p.h index 754d754e74..ba77f7e57c 100644 --- a/src/corelib/thread/qthreadpool_p.h +++ b/src/corelib/thread/qthreadpool_p.h @@ -83,6 +83,7 @@ public: void startThread(QRunnable *runnable = 0); void reset(); bool waitForDone(int msecs); + void clear(); void stealRunnable(QRunnable *); mutable QMutex mutex; diff --git a/tests/auto/corelib/thread/qthreadpool/tst_qthreadpool.cpp b/tests/auto/corelib/thread/qthreadpool/tst_qthreadpool.cpp index fb34afb880..10a59ac301 100644 --- a/tests/auto/corelib/thread/qthreadpool/tst_qthreadpool.cpp +++ b/tests/auto/corelib/thread/qthreadpool/tst_qthreadpool.cpp @@ -97,6 +97,7 @@ private slots: void priorityStart_data(); void priorityStart(); void waitForDone(); + void clear(); void waitForDoneTimeout(); void destroyingWaitsForTasksToFinish(); void stressTest(); @@ -855,6 +856,34 @@ void tst_QThreadPool::waitForDoneTimeout() QVERIFY(threadPool.waitForDone(400)); } +void tst_QThreadPool::clear() +{ + QSemaphore sem(0); + class BlockingRunnable : public QRunnable + { + public: + QSemaphore & sem; + BlockingRunnable(QSemaphore & sem) : sem(sem){} + void run() + { + sem.acquire(); + count.ref(); + } + }; + + QThreadPool threadPool; + threadPool.setMaxThreadCount(10); + int runs = 2 * threadPool.maxThreadCount(); + count.store(0); + for (int i = 0; i <= runs; i++) { + threadPool.start(new BlockingRunnable(sem)); + } + threadPool.clear(); + sem.release(threadPool.maxThreadCount()); + threadPool.waitForDone(); + QCOMPARE(count.load(), threadPool.maxThreadCount()); +} + void tst_QThreadPool::destroyingWaitsForTasksToFinish() { QTime total, pass;