diff options
author | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2021-05-10 17:34:20 +0200 |
---|---|---|
committer | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2021-10-06 14:55:20 +0200 |
commit | 733923c81cd313a02976c026484654e4501b3527 (patch) | |
tree | 10cf0847b668ab7b17c139b38dc9e0d3e21d9109 /src | |
parent | 2c3617dfcb4a5230f51f2d2b2eac0e1fb26206cd (diff) |
Add a safer way to use QThreadPool::reserveThread
Add startOnReservedThread that specifically releases a reserved thread
and uses it atomically for a given task. This can make a positive
number of reserved threads work.
Change-Id: I4bd1dced24bb46fcb365f12cbc9c7905dc66cdf1
Reviewed-by: David Faure <david.faure@kdab.com>
Diffstat (limited to 'src')
-rw-r--r-- | src/corelib/thread/qthreadpool.cpp | 51 | ||||
-rw-r--r-- | src/corelib/thread/qthreadpool.h | 3 |
2 files changed, 54 insertions, 0 deletions
diff --git a/src/corelib/thread/qthreadpool.cpp b/src/corelib/thread/qthreadpool.cpp index 96eae6f3f3..b067522ed2 100644 --- a/src/corelib/thread/qthreadpool.cpp +++ b/src/corelib/thread/qthreadpool.cpp @@ -771,6 +771,57 @@ void QThreadPool::releaseThread() } /*! + Releases a thread previously reserved with reserveThread() and uses it + to run \a runnable. + + Note that the thread pool takes ownership of the \a runnable if + \l{QRunnable::autoDelete()}{runnable->autoDelete()} returns \c true, + and the \a runnable will be deleted automatically by the thread + pool after the \l{QRunnable::run()}{runnable->run()} returns. If + \l{QRunnable::autoDelete()}{runnable->autoDelete()} returns \c false, + ownership of \a runnable remains with the caller. Note that + changing the auto-deletion on \a runnable after calling this + functions results in undefined behavior. + + \note Calling this when no threads are reserved results in + undefined behavior. + + \since 6.3 + \sa reserveThread(), start() +*/ +void QThreadPool::startOnReservedThread(QRunnable *runnable) +{ + if (!runnable) + return releaseThread(); + + Q_D(QThreadPool); + QMutexLocker locker(&d->mutex); + Q_ASSERT(d->reservedThreads > 0); + --d->reservedThreads; + + if (!d->tryStart(runnable)) { + // This can only happen if we reserved max threads, + // and something took the one minimum thread. + d->enqueueTask(runnable, INT_MAX); + } +} + +/*! + \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(); + + startOnReservedThread(QRunnable::create(std::move(functionToRun))); +} + +/*! 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 diff --git a/src/corelib/thread/qthreadpool.h b/src/corelib/thread/qthreadpool.h index f3d7e2254b..853055cb30 100644 --- a/src/corelib/thread/qthreadpool.h +++ b/src/corelib/thread/qthreadpool.h @@ -75,6 +75,9 @@ public: void start(std::function<void()> functionToRun, int priority = 0); bool tryStart(std::function<void()> functionToRun); + void startOnReservedThread(QRunnable *runnable); + void startOnReservedThread(std::function<void()> functionToRun); + int expiryTimeout() const; void setExpiryTimeout(int expiryTimeout); |