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 <david.faure@kdab.com>
This commit is contained in:
Corentin Jabot 2013-07-27 23:02:48 +02:00 committed by The Qt Project
parent 8b86443e36
commit 0d8ba7e349
4 changed files with 59 additions and 0 deletions

View File

@ -308,6 +308,18 @@ bool QThreadPoolPrivate::waitForDone(int msecs)
return queue.isEmpty() && activeThreads == 0;
}
void QThreadPoolPrivate::clear()
{
QMutexLocker locker(&mutex);
for (QList<QPair<QRunnable *, int> >::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

View File

@ -83,6 +83,8 @@ public:
void releaseThread();
bool waitForDone(int msecs = -1);
void clear();
};
QT_END_NAMESPACE

View File

@ -83,6 +83,7 @@ public:
void startThread(QRunnable *runnable = 0);
void reset();
bool waitForDone(int msecs);
void clear();
void stealRunnable(QRunnable *);
mutable QMutex mutex;

View File

@ -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;