diff options
Diffstat (limited to 'src/corelib/thread/qthreadpool.cpp')
-rw-r--r-- | src/corelib/thread/qthreadpool.cpp | 98 |
1 files changed, 57 insertions, 41 deletions
diff --git a/src/corelib/thread/qthreadpool.cpp b/src/corelib/thread/qthreadpool.cpp index b1078dab18..ae584656fe 100644 --- a/src/corelib/thread/qthreadpool.cpp +++ b/src/corelib/thread/qthreadpool.cpp @@ -6,6 +6,8 @@ #include "qdeadlinetimer.h" #include "qcoreapplication.h" +#include <QtCore/qpointer.h> + #include <algorithm> #include <memory> @@ -87,7 +89,7 @@ void QThreadPoolThread::run() if (manager->queue.isEmpty()) break; - QueuePage *page = manager->queue.first(); + QueuePage *page = manager->queue.constFirst(); r = page->pop(); if (page->isFinished()) { @@ -188,7 +190,7 @@ inline bool comparePriority(int priority, const QueuePage *p) void QThreadPoolPrivate::enqueueTask(QRunnable *runnable, int priority) { Q_ASSERT(runnable != nullptr); - for (QueuePage *page : qAsConst(queue)) { + for (QueuePage *page : std::as_const(queue)) { if (page->priority() == priority && !page->isFull()) { page->push(runnable); return; @@ -200,9 +202,9 @@ void QThreadPoolPrivate::enqueueTask(QRunnable *runnable, int priority) int QThreadPoolPrivate::activeThreadCount() const { - return (allThreads.count() - - expiredThreads.count() - - waitingThreads.count() + return (allThreads.size() + - expiredThreads.size() + - waitingThreads.size() + reservedThreads); } @@ -210,7 +212,7 @@ void QThreadPoolPrivate::tryToStartMoreThreads() { // try to push tasks on the queue to any available threads while (!queue.isEmpty()) { - QueuePage *page = queue.first(); + QueuePage *page = queue.constFirst(); if (!tryStart(page->first())) break; @@ -269,7 +271,7 @@ void QThreadPoolPrivate::reset() mutex.unlock(); - for (QThreadPoolThread *thread : qAsConst(allThreadsCopy)) { + for (QThreadPoolThread *thread : std::as_const(allThreadsCopy)) { if (thread->isRunning()) { thread->runnableReady.wakeAll(); thread->wait(); @@ -348,7 +350,7 @@ bool QThreadPool::tryTake(QRunnable *runnable) return false; QMutexLocker locker(&d->mutex); - for (QueuePage *page : qAsConst(d->queue)) { + for (QueuePage *page : std::as_const(d->queue)) { if (page->tryTake(runnable)) { if (page->isFinished()) { d->queue.removeOne(page); @@ -475,6 +477,21 @@ QThreadPool *QThreadPool::globalInstance() } /*! + Returns the QThreadPool instance for Qt Gui. + \internal +*/ +QThreadPool *QThreadPoolPrivate::qtGuiInstance() +{ + Q_CONSTINIT static QPointer<QThreadPool> guiInstance; + Q_CONSTINIT static QBasicMutex theMutex; + + const QMutexLocker locker(&theMutex); + if (guiInstance.isNull() && !QCoreApplication::closingDown()) + guiInstance = new QThreadPool(); + return guiInstance; +} + +/*! Reserves a thread and uses it to run \a runnable, unless this thread will make the current thread count exceed maxThreadCount(). In that case, \a runnable is added to a run queue instead. The \a priority argument can @@ -502,20 +519,21 @@ void QThreadPool::start(QRunnable *runnable, int priority) } /*! + \fn template<typename Callable, QRunnable::if_callable<Callable>> void QThreadPool::start(Callable &&callableToRun, int priority) \overload \since 5.15 - Reserves a thread and uses it to run \a functionToRun, unless this thread will + Reserves a thread and uses it to run \a callableToRun, unless this thread will make the current thread count exceed maxThreadCount(). In that case, - \a functionToRun is added to a run queue instead. The \a priority argument can + \a callableToRun is added to a run queue instead. The \a priority argument can be used to control the run queue's order of execution. + + \note This function participates in overload resolution only if \c Callable + is a function or function object which can be called with zero arguments. + + \note In Qt version prior to 6.6, this function took std::function<void()>, + and therefore couldn't handle move-only callables. */ -void QThreadPool::start(std::function<void()> functionToRun, int priority) -{ - if (!functionToRun) - return; - start(QRunnable::create(std::move(functionToRun)), priority); -} /*! Attempts to reserve a thread to run \a runnable. @@ -547,30 +565,21 @@ bool QThreadPool::tryStart(QRunnable *runnable) } /*! + \fn template<typename Callable, QRunnable::if_callable<Callable>> bool QThreadPool::tryStart(Callable &&callableToRun) \overload \since 5.15 - Attempts to reserve a thread to run \a functionToRun. + Attempts to reserve a thread to run \a callableToRun. If no threads are available at the time of calling, then this function - does nothing and returns \c false. Otherwise, \a functionToRun is run immediately + does nothing and returns \c false. Otherwise, \a callableToRun is run immediately using one available thread and this function returns \c true. -*/ -bool QThreadPool::tryStart(std::function<void()> functionToRun) -{ - if (!functionToRun) - return false; - Q_D(QThreadPool); - QMutexLocker locker(&d->mutex); - if (!d->allThreads.isEmpty() && d->areAllThreadsActive()) - return false; + \note This function participates in overload resolution only if \c Callable + is a function or function object which can be called with zero arguments. - QRunnable *runnable = QRunnable::create(std::move(functionToRun)); - if (d->tryStart(runnable)) - return true; - delete runnable; - return false; -} + \note In Qt version prior to 6.6, this function took std::function<void()>, + and therefore couldn't handle move-only callables. +*/ /*! \property QThreadPool::expiryTimeout \brief the thread expiry timeout value in milliseconds. @@ -590,12 +599,14 @@ bool QThreadPool::tryStart(std::function<void()> functionToRun) int QThreadPool::expiryTimeout() const { Q_D(const QThreadPool); + QMutexLocker locker(&d->mutex); return d->expiryTimeout; } void QThreadPool::setExpiryTimeout(int expiryTimeout) { Q_D(QThreadPool); + QMutexLocker locker(&d->mutex); if (d->expiryTimeout == expiryTimeout) return; d->expiryTimeout = expiryTimeout; @@ -616,6 +627,7 @@ void QThreadPool::setExpiryTimeout(int expiryTimeout) int QThreadPool::maxThreadCount() const { Q_D(const QThreadPool); + QMutexLocker locker(&d->mutex); return d->requestedMaxThreadCount; } @@ -685,12 +697,14 @@ void QThreadPool::reserveThread() void QThreadPool::setStackSize(uint stackSize) { Q_D(QThreadPool); + QMutexLocker locker(&d->mutex); d->stackSize = stackSize; } uint QThreadPool::stackSize() const { Q_D(const QThreadPool); + QMutexLocker locker(&d->mutex); return d->stackSize; } @@ -711,12 +725,14 @@ uint QThreadPool::stackSize() const void QThreadPool::setThreadPriority(QThread::Priority priority) { Q_D(QThreadPool); + QMutexLocker locker(&d->mutex); d->threadPriority = priority; } QThread::Priority QThreadPool::threadPriority() const { Q_D(const QThreadPool); + QMutexLocker locker(&d->mutex); return d->threadPriority; } @@ -777,19 +793,19 @@ void QThreadPool::startOnReservedThread(QRunnable *runnable) } /*! + \fn template<typename Callable, QRunnable::if_callable<Callable>> void QThreadPool::startOnReservedThread(Callable &&callableToRun) \overload \since 6.3 Releases a thread previously reserved with reserveThread() and uses it - to run \a functionToRun. -*/ -void QThreadPool::startOnReservedThread(std::function<void()> functionToRun) -{ - if (!functionToRun) - return releaseThread(); + to run \a callableToRun. - startOnReservedThread(QRunnable::create(std::move(functionToRun))); -} + \note This function participates in overload resolution only if \c Callable + is a function or function object which can be called with zero arguments. + + \note In Qt version prior to 6.6, this function took std::function<void()>, + and therefore couldn't handle move-only callables. +*/ /*! Waits up to \a msecs milliseconds for all threads to exit and removes all |