QThreadPool: obey the docs that say we always use at least 1 thread

Even if the user (usually accidentally) sets a thread count of zero or
negative. The reporter in the bug report did
QThread::idealThreadCount() - 1 on a 1 CPU system...

Drive-by add to the documentation and the missing #include.

Pick-to: 6.1 6.0
Fixes: QTBUG-93007
Change-Id: I6cdea00671e8479b9c50fffd167807d14e030154
Reviewed-by: Samuel Gaist <samuel.gaist@idiap.ch>
Reviewed-by: Sona Kurazyan <sona.kurazyan@qt.io>
This commit is contained in:
Thiago Macieira 2021-04-21 17:51:01 -07:00 committed by Samuel Gaist
parent ddaa7150d8
commit 885eff0537
3 changed files with 14 additions and 9 deletions

View File

@ -176,7 +176,7 @@ bool QThreadPoolPrivate::tryStart(QRunnable *task)
}
// can't do anything if we're over the limit
if (activeThreadCount() >= maxThreadCount)
if (activeThreadCount() >= maxThreadCount())
return false;
if (waitingThreads.count() > 0) {
@ -249,7 +249,7 @@ void QThreadPoolPrivate::tryToStartMoreThreads()
bool QThreadPoolPrivate::tooManyThreadsActive() const
{
const int activeThreadCount = this->activeThreadCount();
return activeThreadCount > maxThreadCount && (activeThreadCount - reservedThreads) > 1;
return activeThreadCount > maxThreadCount() && (activeThreadCount - reservedThreads) > 1;
}
/*!
@ -577,7 +577,7 @@ bool QThreadPool::tryStart(std::function<void()> functionToRun)
Q_D(QThreadPool);
QMutexLocker locker(&d->mutex);
if (!d->allThreads.isEmpty() && d->activeThreadCount() >= d->maxThreadCount)
if (!d->allThreads.isEmpty() && d->activeThreadCount() >= d->maxThreadCount())
return false;
QRunnable *runnable = QRunnable::create(std::move(functionToRun));
@ -618,7 +618,9 @@ void QThreadPool::setExpiryTimeout(int expiryTimeout)
/*! \property QThreadPool::maxThreadCount
\brief the maximum number of threads used by the thread pool.
\brief the maximum number of threads used by the thread pool. This property
will default to the value of QThread::idealThreadCount() at the moment the
QThreadPool object is created.
\note The thread pool will always use at least 1 thread, even if
\a maxThreadCount limit is zero or negative.
@ -629,7 +631,7 @@ void QThreadPool::setExpiryTimeout(int expiryTimeout)
int QThreadPool::maxThreadCount() const
{
Q_D(const QThreadPool);
return d->maxThreadCount;
return d->requestedMaxThreadCount;
}
void QThreadPool::setMaxThreadCount(int maxThreadCount)
@ -637,10 +639,10 @@ void QThreadPool::setMaxThreadCount(int maxThreadCount)
Q_D(QThreadPool);
QMutexLocker locker(&d->mutex);
if (maxThreadCount == d->maxThreadCount)
if (maxThreadCount == d->requestedMaxThreadCount)
return;
d->maxThreadCount = maxThreadCount;
d->requestedMaxThreadCount = maxThreadCount;
d->tryToStartMoreThreads();
}

View File

@ -55,6 +55,7 @@
#include "QtCore/qmutex.h"
#include "QtCore/qthread.h"
#include "QtCore/qwaitcondition.h"
#include "QtCore/qthreadpool.h"
#include "QtCore/qset.h"
#include "QtCore/qqueue.h"
#include "private/qobject_p.h"
@ -158,6 +159,8 @@ public:
void tryToStartMoreThreads();
bool tooManyThreadsActive() const;
int maxThreadCount() const
{ return qMax(requestedMaxThreadCount, 1); } // documentation says we start at least one
void startThread(QRunnable *runnable = nullptr);
void reset();
bool waitForDone(int msecs);
@ -174,7 +177,7 @@ public:
QWaitCondition noActiveThreads;
int expiryTimeout = 30000;
int maxThreadCount = QThread::idealThreadCount();
int requestedMaxThreadCount = QThread::idealThreadCount(); // don't use this directly
int reservedThreads = 0;
int activeThreads = 0;
uint stackSize = 0;

View File

@ -506,7 +506,7 @@ void tst_QThreadPool::setMaxThreadCountStartsAndStopsThreads()
};
QThreadPool threadPool;
threadPool.setMaxThreadCount(1);
threadPool.setMaxThreadCount(-1); // docs say we'll always start at least one
WaitingTask task;
threadPool.start(&task);