From 179e79b18d1827e38d8ffe2914e5d15b12e270d5 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Mon, 6 May 2024 10:53:06 -0700 Subject: [PATCH] QThreadPool: add waitForDone() based on QDeadlineTimer It was already being used internally this way, so all we needed was to provide the front-end API and inline the old API. [ChangeLog][QtCore][QThreadPool] Added an overload of waitForDone() based on QDeadlineTimer. Fixes: QTBUG-125107 Change-Id: Ic5b1273bb0204c31afd8fffd17ccf7c5bee07c35 Reviewed-by: Ahmad Samir --- src/corelib/compat/removed_api.cpp | 4 ++++ src/corelib/thread/qthreadpool.cpp | 32 +++++++++++++++++------------- src/corelib/thread/qthreadpool.h | 11 +++++++++- src/corelib/thread/qthreadpool_p.h | 1 - 4 files changed, 32 insertions(+), 16 deletions(-) diff --git a/src/corelib/compat/removed_api.cpp b/src/corelib/compat/removed_api.cpp index ed285dc8f12..3c6123ed155 100644 --- a/src/corelib/compat/removed_api.cpp +++ b/src/corelib/compat/removed_api.cpp @@ -1078,6 +1078,10 @@ bool QRegularExpression::operator==(const QRegularExpression &other) const #include "qstring.h" // inlined API +#if QT_CONFIG(thread) +# include "qthreadpool.h" // inlined API +#endif + #include "qurl.h" bool QUrl::operator<(const QUrl &url) const diff --git a/src/corelib/thread/qthreadpool.cpp b/src/corelib/thread/qthreadpool.cpp index ae584656fe5..69d9afc77a6 100644 --- a/src/corelib/thread/qthreadpool.cpp +++ b/src/corelib/thread/qthreadpool.cpp @@ -258,7 +258,7 @@ void QThreadPoolPrivate::startThread(QRunnable *runnable) /*! \internal - Helper function only to be called from waitForDone(int) + Helper function only to be called from waitForDone() Deletes all current threads. */ @@ -285,22 +285,17 @@ void QThreadPoolPrivate::reset() /*! \internal - Helper function only to be called from waitForDone(int) + Helper function only to be called from the public waitForDone() */ bool QThreadPoolPrivate::waitForDone(const QDeadlineTimer &timer) { + QMutexLocker locker(&mutex); while (!(queue.isEmpty() && activeThreads == 0) && !timer.hasExpired()) noActiveThreads.wait(&mutex, timer); - return queue.isEmpty() && activeThreads == 0; -} - -bool QThreadPoolPrivate::waitForDone(int msecs) -{ - QMutexLocker locker(&mutex); - QDeadlineTimer timer(msecs); - if (!waitForDone(timer)) + if (!queue.isEmpty() || activeThreads) return false; + reset(); // New jobs might have started during reset, but return anyway // as the active thread and task count did reach 0 once, and @@ -808,15 +803,24 @@ void QThreadPool::startOnReservedThread(QRunnable *runnable) */ /*! + \fn bool QThreadPool::waitForDone(int msecs) Waits up to \a msecs milliseconds for all threads to exit and removes all threads from the thread pool. Returns \c true if all threads were removed; - otherwise it returns \c false. If \a msecs is -1 (the default), the timeout - is ignored (waits for the last thread to exit). + otherwise it returns \c false. If \a msecs is -1, this function waits for + the last thread to exit. */ -bool QThreadPool::waitForDone(int msecs) + +/*! + \since 6.8 + + Waits until \a deadline expires for all threads to exit and removes all + threads from the thread pool. Returns \c true if all threads were removed; + otherwise it returns \c false. +*/ +bool QThreadPool::waitForDone(QDeadlineTimer deadline) { Q_D(QThreadPool); - return d->waitForDone(msecs); + return d->waitForDone(deadline); } /*! diff --git a/src/corelib/thread/qthreadpool.h b/src/corelib/thread/qthreadpool.h index 8f0130bd843..0640f415872 100644 --- a/src/corelib/thread/qthreadpool.h +++ b/src/corelib/thread/qthreadpool.h @@ -72,7 +72,9 @@ public: void reserveThread(); void releaseThread(); - bool waitForDone(int msecs = -1); + QT_CORE_INLINE_SINCE(6, 8) + bool waitForDone(int msecs); + bool waitForDone(QDeadlineTimer deadline = QDeadlineTimer::Forever); void clear(); @@ -103,6 +105,13 @@ void QThreadPool::startOnReservedThread(Callable &&functionToRun) startOnReservedThread(QRunnable::create(std::forward(functionToRun))); } +#if QT_CORE_INLINE_IMPL_SINCE(6, 8) +bool QThreadPool::waitForDone(int msecs) +{ + return waitForDone(QDeadlineTimer(msecs)); +} +#endif + QT_END_NAMESPACE #endif diff --git a/src/corelib/thread/qthreadpool_p.h b/src/corelib/thread/qthreadpool_p.h index 67c703fabd9..1864385c629 100644 --- a/src/corelib/thread/qthreadpool_p.h +++ b/src/corelib/thread/qthreadpool_p.h @@ -128,7 +128,6 @@ public: { return qMax(requestedMaxThreadCount, 1); } // documentation says we start at least one void startThread(QRunnable *runnable = nullptr); void reset(); - bool waitForDone(int msecs); bool waitForDone(const QDeadlineTimer &timer); void clear(); void stealAndRunRunnable(QRunnable *runnable);