diff options
Diffstat (limited to 'src/corelib/thread/qthreadpool.cpp')
-rw-r--r-- | src/corelib/thread/qthreadpool.cpp | 65 |
1 files changed, 48 insertions, 17 deletions
diff --git a/src/corelib/thread/qthreadpool.cpp b/src/corelib/thread/qthreadpool.cpp index a7d52f9652..9ef40a5209 100644 --- a/src/corelib/thread/qthreadpool.cpp +++ b/src/corelib/thread/qthreadpool.cpp @@ -52,14 +52,14 @@ QT_BEGIN_NAMESPACE Q_GLOBAL_STATIC(QThreadPool, theInstance) /* - QThread wrapper, provides synchronizitaion against a ThreadPool + QThread wrapper, provides synchronization against a ThreadPool */ class QThreadPoolThread : public QThread { public: QThreadPoolThread(QThreadPoolPrivate *manager); void run(); - void registerTheadInactive(); + void registerThreadInactive(); QThreadPoolPrivate *manager; QRunnable *runnable; @@ -103,7 +103,7 @@ void QThreadPoolThread::run() qWarning("Qt Concurrent has caught an exception thrown from a worker thread.\n" "This is not supported, exceptions thrown in worker threads must be\n" "caught before control returns to Qt Concurrent."); - registerTheadInactive(); + registerThreadInactive(); throw; } #endif @@ -121,7 +121,7 @@ void QThreadPoolThread::run() } while (r != 0); if (manager->isExiting) { - registerTheadInactive(); + registerThreadInactive(); break; } @@ -129,7 +129,7 @@ void QThreadPoolThread::run() bool expired = manager->tooManyThreadsActive(); if (!expired) { ++manager->waitingThreads; - registerTheadInactive(); + registerThreadInactive(); // wait for work, exiting after the expiry timeout is reached expired = !manager->runnableReady.wait(locker.mutex(), manager->expiryTimeout); ++manager->activeThreads; @@ -139,13 +139,13 @@ void QThreadPoolThread::run() } if (expired) { manager->expiredThreads.enqueue(this); - registerTheadInactive(); + registerThreadInactive(); break; } } } -void QThreadPoolThread::registerTheadInactive() +void QThreadPoolThread::registerThreadInactive() { if (--manager->activeThreads == 0) manager->noActiveThreads.wakeAll(); @@ -180,6 +180,7 @@ bool QThreadPoolPrivate::tryStart(QRunnable *task) // recycle an available thread --waitingThreads; enqueueTask(task); + runnableReady.wakeOne(); return true; } @@ -218,13 +219,10 @@ void QThreadPoolPrivate::enqueueTask(QRunnable *runnable, int priority) if (it != begin && priority > (*(it - 1)).second) it = std::upper_bound(begin, --it, priority); queue.insert(it - begin, qMakePair(runnable, priority)); - runnableReady.wakeOne(); } int QThreadPoolPrivate::activeThreadCount() const { - // To improve scalability this function is called without holding - // the mutex lock -- keep it thread-safe. return (allThreads.count() - expiredThreads.count() - waitingThreads @@ -262,7 +260,7 @@ void QThreadPoolPrivate::startThread(QRunnable *runnable) /*! \internal - Makes all threads exit, waits for each tread to exit and deletes it. + Makes all threads exit, waits for each thread to exit and deletes it. */ void QThreadPoolPrivate::reset() { @@ -308,10 +306,22 @@ 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 - runs it if found. This functon does not return until the runnable + Searches for \a runnable in the queue, removes it from the queue and + runs it if found. This function does not return until the runnable has completed. */ void QThreadPoolPrivate::stealRunnable(QRunnable *runnable) @@ -446,8 +456,14 @@ void QThreadPool::start(QRunnable *runnable, int priority) Q_D(QThreadPool); QMutexLocker locker(&d->mutex); - if (!d->tryStart(runnable)) + if (!d->tryStart(runnable)) { d->enqueueTask(runnable, priority); + + if (d->waitingThreads > 0) { + --d->waitingThreads; + d->runnableReady.wakeOne(); + } + } } /*! @@ -473,12 +489,11 @@ bool QThreadPool::tryStart(QRunnable *runnable) Q_D(QThreadPool); - // To improve scalability perform a check on the thread count - // before locking the mutex. + QMutexLocker locker(&d->mutex); + if (d->allThreads.isEmpty() == false && d->activeThreadCount() >= d->maxThreadCount) return false; - QMutexLocker locker(&d->mutex); return d->tryStart(runnable); } @@ -552,6 +567,7 @@ void QThreadPool::setMaxThreadCount(int maxThreadCount) int QThreadPool::activeThreadCount() const { Q_D(const QThreadPool); + QMutexLocker locker(&d->mutex); return d->activeThreadCount(); } @@ -609,6 +625,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 |