From e58d714c4750b49bf255a0f42b63118534df8a24 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A5rten=20Nordheim?= Date: Fri, 4 Oct 2024 15:55:38 +0200 Subject: [PATCH] QThreadPool: Add Quality of Service API MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Same limitation as setting priority; it only applies to threads that start after the call. Change-Id: I0f77467a76ce2f4e7743d04fde344ef08cd8dbb8 Reviewed-by: Tor Arne Vestbø --- src/corelib/thread/qthreadpool.cpp | 33 +++++++++++++++++++ src/corelib/thread/qthreadpool.h | 3 ++ src/corelib/thread/qthreadpool_p.h | 1 + .../thread/qthreadpool/tst_qthreadpool.cpp | 13 ++++++++ 4 files changed, 50 insertions(+) diff --git a/src/corelib/thread/qthreadpool.cpp b/src/corelib/thread/qthreadpool.cpp index 55f13a6b02a..62e3773af95 100644 --- a/src/corelib/thread/qthreadpool.cpp +++ b/src/corelib/thread/qthreadpool.cpp @@ -249,6 +249,7 @@ void QThreadPoolPrivate::startThread(QRunnable *runnable) if (objectName.isEmpty()) objectName = u"Thread (pooled)"_s; thread->setObjectName(objectName); + thread->setServiceLevel(serviceLevel); Q_ASSERT(!allThreads.contains(thread.get())); // if this assert hits, we have an ABA problem (deleted threads don't get removed here) allThreads.insert(thread.get()); ++activeThreads; @@ -764,6 +765,38 @@ void QThreadPool::releaseThread() d->tryToStartMoreThreads(); } +/*! + \since 6.9 + + Sets the Quality of Service level of thread objects created after the call + to this setter to \a serviceLevel. + + Support is not available on every platform. Consult + QThread::setServiceLevel() for details. + + \sa serviceLevel(), QThread::serviceLevel() +*/ +void QThreadPool::setServiceLevel(QThread::QualityOfService serviceLevel) +{ + Q_D(QThreadPool); + QMutexLocker locker(&d->mutex); + d->serviceLevel = serviceLevel; +} + +/*! + \since 6.9 + + Returns the current Quality of Service level of the thread. + + \sa setServiceLevel(), QThread::serviceLevel() +*/ +QThread::QualityOfService QThreadPool::serviceLevel() const +{ + Q_D(const QThreadPool); + QMutexLocker locker(&d->mutex); + return d->serviceLevel; +} + /*! Releases a thread previously reserved with reserveThread() and uses it to run \a runnable. diff --git a/src/corelib/thread/qthreadpool.h b/src/corelib/thread/qthreadpool.h index 0640f415872..d471bb39d83 100644 --- a/src/corelib/thread/qthreadpool.h +++ b/src/corelib/thread/qthreadpool.h @@ -72,6 +72,9 @@ public: void reserveThread(); void releaseThread(); + void setServiceLevel(QThread::QualityOfService serviceLevel); + QThread::QualityOfService serviceLevel() const; + QT_CORE_INLINE_SINCE(6, 8) bool waitForDone(int msecs); bool waitForDone(QDeadlineTimer deadline = QDeadlineTimer::Forever); diff --git a/src/corelib/thread/qthreadpool_p.h b/src/corelib/thread/qthreadpool_p.h index 7910592f70d..284cf21e4fd 100644 --- a/src/corelib/thread/qthreadpool_p.h +++ b/src/corelib/thread/qthreadpool_p.h @@ -149,6 +149,7 @@ public: int activeThreads = 0; uint stackSize = 0; QThread::Priority threadPriority = QThread::InheritPriority; + QThread::QualityOfService serviceLevel = QThread::QualityOfService::Auto; }; QT_END_NAMESPACE diff --git a/tests/auto/corelib/thread/qthreadpool/tst_qthreadpool.cpp b/tests/auto/corelib/thread/qthreadpool/tst_qthreadpool.cpp index 6decea9b939..0c6c74b95ec 100644 --- a/tests/auto/corelib/thread/qthreadpool/tst_qthreadpool.cpp +++ b/tests/auto/corelib/thread/qthreadpool/tst_qthreadpool.cpp @@ -76,6 +76,7 @@ private slots: void tryStartCount(); void priorityStart_data(); void priorityStart(); + void qualityOfService(); void waitForDone(); void clear(); void clearWithAutoDelete(); @@ -1046,6 +1047,18 @@ void tst_QThreadPool::priorityStart() QCOMPARE(firstStarted.loadRelaxed(), expected); } +void tst_QThreadPool::qualityOfService() +{ + QThreadPool p; + p.setServiceLevel(QThread::QualityOfService::Eco); + QThread::QualityOfService level = QThread::QualityOfService::Auto; + p.tryStart([&level](){ + level = QThread::currentThread()->serviceLevel(); + }); + QVERIFY(p.waitForDone(QDeadlineTimer(10s))); + QCOMPARE(level, QThread::QualityOfService::Eco); +} + void tst_QThreadPool::waitForDone() { QElapsedTimer total, pass;