summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2023-02-24 10:57:56 +0100
committerQt Cherry-pick Bot <cherrypick_bot@qt-project.org>2023-02-25 12:18:09 +0000
commit8f2a3714dca5143ba3f919bdebb3e11e5a6c7cc3 (patch)
tree9abd16c0b0ae015c23eddef4475ce6535cbe74ee
parent41836354e6e98cb54208282a0fdb8e8b599b7101 (diff)
downloadqtbase-8f2a3714dca5143ba3f919bdebb3e11e5a6c7cc3.tar.gz
Add special thread pool for Qt Gui
To avoid gui slowdowns due to global pool being blocked. Fixes: QTBUG-109511 Change-Id: I4e8d91e8fb0bd2e395072a082e992a3c5d3464ad Reviewed-by: MÃ¥rten Nordheim <marten.nordheim@qt.io> (cherry picked from commit 93047c71e8e6dd4ac28e1e59dcb561df11c759eb) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
-rw-r--r--src/corelib/kernel/qcoreapplication.cpp7
-rw-r--r--src/corelib/thread/qthreadpool.cpp15
-rw-r--r--src/corelib/thread/qthreadpool_p.h2
-rw-r--r--src/gui/image/qimage.cpp7
-rw-r--r--src/gui/image/qimage_conversions.cpp13
-rw-r--r--src/gui/painting/qdrawhelper.cpp5
-rw-r--r--src/gui/painting/qimagescale.cpp7
-rw-r--r--src/gui/painting/qimagescale_neon.cpp7
-rw-r--r--src/gui/painting/qimagescale_sse4.cpp7
9 files changed, 50 insertions, 20 deletions
diff --git a/src/corelib/kernel/qcoreapplication.cpp b/src/corelib/kernel/qcoreapplication.cpp
index 2a55a8a87e..355d1e42cc 100644
--- a/src/corelib/kernel/qcoreapplication.cpp
+++ b/src/corelib/kernel/qcoreapplication.cpp
@@ -31,6 +31,7 @@
#include <private/qthread_p.h>
#if QT_CONFIG(thread)
#include <qthreadpool.h>
+#include <private/qthreadpool_p.h>
#endif
#endif
#include <qelapsedtimer.h>
@@ -855,8 +856,10 @@ QCoreApplication::~QCoreApplication()
#if QT_CONFIG(thread)
// Synchronize and stop the global thread pool threads.
QThreadPool *globalThreadPool = nullptr;
+ QThreadPool *guiThreadPool = nullptr;
QT_TRY {
globalThreadPool = QThreadPool::globalInstance();
+ guiThreadPool = QThreadPoolPrivate::qtGuiInstance();
} QT_CATCH (...) {
// swallow the exception, since destructors shouldn't throw
}
@@ -864,6 +867,10 @@ QCoreApplication::~QCoreApplication()
globalThreadPool->waitForDone();
delete globalThreadPool;
}
+ if (guiThreadPool) {
+ guiThreadPool->waitForDone();
+ delete guiThreadPool;
+ }
#endif
#ifndef QT_NO_QOBJECT
diff --git a/src/corelib/thread/qthreadpool.cpp b/src/corelib/thread/qthreadpool.cpp
index bb7e232f42..51783321b9 100644
--- a/src/corelib/thread/qthreadpool.cpp
+++ b/src/corelib/thread/qthreadpool.cpp
@@ -475,6 +475,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
diff --git a/src/corelib/thread/qthreadpool_p.h b/src/corelib/thread/qthreadpool_p.h
index f967880bde..67c703fabd 100644
--- a/src/corelib/thread/qthreadpool_p.h
+++ b/src/corelib/thread/qthreadpool_p.h
@@ -134,6 +134,8 @@ public:
void stealAndRunRunnable(QRunnable *runnable);
void deletePageIfFinished(QueuePage *page);
+ static QThreadPool *qtGuiInstance();
+
mutable QMutex mutex;
QSet<QThreadPoolThread *> allThreads;
QQueue<QThreadPoolThread *> waitingThreads;
diff --git a/src/gui/image/qimage.cpp b/src/gui/image/qimage.cpp
index bd9115a34b..42c6a3fc0b 100644
--- a/src/gui/image/qimage.cpp
+++ b/src/gui/image/qimage.cpp
@@ -35,8 +35,9 @@
#include <private/qfont_p.h>
#if QT_CONFIG(thread)
-#include "qsemaphore.h"
-#include "qthreadpool.h"
+#include <qsemaphore.h>
+#include <qthreadpool.h>
+#include <private/qthreadpool_p.h>
#endif
#include <qtgui_tracepoints_p.h>
@@ -5105,7 +5106,7 @@ void QImage::applyColorTransform(const QColorTransform &transform)
#if QT_CONFIG(thread) && !defined(Q_OS_WASM)
int segments = (qsizetype(width()) * height()) >> 16;
segments = std::min(segments, height());
- QThreadPool *threadPool = QThreadPool::globalInstance();
+ QThreadPool *threadPool = QThreadPoolPrivate::qtGuiInstance();
if (segments > 1 && threadPool && !threadPool->contains(QThread::currentThread())) {
QSemaphore semaphore;
int y = 0;
diff --git a/src/gui/image/qimage_conversions.cpp b/src/gui/image/qimage_conversions.cpp
index fa75bed3c8..5aa02acb4e 100644
--- a/src/gui/image/qimage_conversions.cpp
+++ b/src/gui/image/qimage_conversions.cpp
@@ -15,6 +15,7 @@
#if QT_CONFIG(thread)
#include <qsemaphore.h>
#include <qthreadpool.h>
+#include <private/qthreadpool_p.h>
#ifdef Q_OS_WASM
// WebAssembly has threads; however we can't block the main thread.
#else
@@ -203,7 +204,7 @@ void convert_generic(QImageData *dest, const QImageData *src, Qt::ImageConversio
int segments = (qsizetype(src->width) * src->height) >> 16;
segments = std::min(segments, src->height);
- QThreadPool *threadPool = QThreadPool::globalInstance();
+ QThreadPool *threadPool = QThreadPoolPrivate::qtGuiInstance();
if (segments <= 1 || !threadPool || threadPool->contains(QThread::currentThread()))
return convertSegment(0, src->height);
@@ -258,7 +259,7 @@ void convert_generic_over_rgb64(QImageData *dest, const QImageData *src, Qt::Ima
int segments = (qsizetype(src->width) * src->height) >> 16;
segments = std::min(segments, src->height);
- QThreadPool *threadPool = QThreadPool::globalInstance();
+ QThreadPool *threadPool = QThreadPoolPrivate::qtGuiInstance();
if (segments <= 1 || !threadPool || threadPool->contains(QThread::currentThread()))
return convertSegment(0, src->height);
@@ -312,7 +313,7 @@ void convert_generic_over_rgba32f(QImageData *dest, const QImageData *src, Qt::I
int segments = (qsizetype(src->width) * src->height) >> 16;
segments = std::min(segments, src->height);
- QThreadPool *threadPool = QThreadPool::globalInstance();
+ QThreadPool *threadPool = QThreadPoolPrivate::qtGuiInstance();
if (segments <= 1 || !threadPool || threadPool->contains(QThread::currentThread()))
return convertSegment(0, src->height);
@@ -419,7 +420,7 @@ bool convert_generic_inplace(QImageData *data, QImage::Format dst_format, Qt::Im
#ifdef QT_USE_THREAD_PARALLEL_IMAGE_CONVERSIONS
int segments = (qsizetype(data->width) * data->height) >> 16;
segments = std::min(segments, data->height);
- QThreadPool *threadPool = QThreadPool::globalInstance();
+ QThreadPool *threadPool = QThreadPoolPrivate::qtGuiInstance();
if (segments > 1 && threadPool && !threadPool->contains(QThread::currentThread())) {
QSemaphore semaphore;
int y = 0;
@@ -513,7 +514,7 @@ bool convert_generic_inplace_over_rgb64(QImageData *data, QImage::Format dst_for
#ifdef QT_USE_THREAD_PARALLEL_IMAGE_CONVERSIONS
int segments = (qsizetype(data->width) * data->height) >> 16;
segments = std::min(segments, data->height);
- QThreadPool *threadPool = QThreadPool::globalInstance();
+ QThreadPool *threadPool = QThreadPoolPrivate::qtGuiInstance();
if (segments > 1 && threadPool && !threadPool->contains(QThread::currentThread())) {
QSemaphore semaphore;
int y = 0;
@@ -608,7 +609,7 @@ bool convert_generic_inplace_over_rgba32f(QImageData *data, QImage::Format dst_f
#ifdef QT_USE_THREAD_PARALLEL_IMAGE_CONVERSIONS
int segments = (qsizetype(data->width) * data->height) >> 16;
segments = std::min(segments, data->height);
- QThreadPool *threadPool = QThreadPool::globalInstance();
+ QThreadPool *threadPool = QThreadPoolPrivate::qtGuiInstance();
if (segments > 1 && threadPool && !threadPool->contains(QThread::currentThread())) {
QSemaphore semaphore;
int y = 0;
diff --git a/src/gui/painting/qdrawhelper.cpp b/src/gui/painting/qdrawhelper.cpp
index 39ea82e910..89db5b9bcd 100644
--- a/src/gui/painting/qdrawhelper.cpp
+++ b/src/gui/painting/qdrawhelper.cpp
@@ -32,6 +32,7 @@
#if defined(QT_USE_THREAD_PARALLEL_FILLS)
#include <qsemaphore.h>
#include <qthreadpool.h>
+#include <private/qthreadpool_p.h>
#endif
QT_BEGIN_NAMESPACE
@@ -3778,7 +3779,7 @@ static void spanfill_from_first(QRasterBuffer *rasterBuffer, QPixelLayout::BPP b
#if defined(QT_USE_THREAD_PARALLEL_FILLS)
#define QT_THREAD_PARALLEL_FILLS(function) \
const int segments = (count + 32) / 64; \
- QThreadPool *threadPool = QThreadPool::globalInstance(); \
+ QThreadPool *threadPool = QThreadPoolPrivate::qtGuiInstance(); \
if (segments > 1 && threadPool && !threadPool->contains(QThread::currentThread())) { \
QSemaphore semaphore; \
int c = 0; \
@@ -3787,7 +3788,7 @@ static void spanfill_from_first(QRasterBuffer *rasterBuffer, QPixelLayout::BPP b
threadPool->start([&, c, cn]() { \
function(c, c + cn); \
semaphore.release(1); \
- }); \
+ }, 1); \
c += cn; \
} \
semaphore.acquire(segments); \
diff --git a/src/gui/painting/qimagescale.cpp b/src/gui/painting/qimagescale.cpp
index 80d1a67a3f..a636635fd5 100644
--- a/src/gui/painting/qimagescale.cpp
+++ b/src/gui/painting/qimagescale.cpp
@@ -10,8 +10,9 @@
#include "qrgbafloat.h"
#if QT_CONFIG(thread) && !defined(Q_OS_WASM)
-#include "qsemaphore.h"
-#include "qthreadpool.h"
+#include <qsemaphore.h>
+#include <qthreadpool.h>
+#include <private/qthreadpool_p.h>
#endif
QT_BEGIN_NAMESPACE
@@ -273,7 +274,7 @@ static inline void multithread_pixels_function(QImageScaleInfo *isi, int dh, con
#if QT_CONFIG(thread) && !defined(Q_OS_WASM)
int segments = (qsizetype(isi->sh) * isi->sw) / (1<<16);
segments = std::min(segments, dh);
- QThreadPool *threadPool = QThreadPool::globalInstance();
+ QThreadPool *threadPool = QThreadPoolPrivate::qtGuiInstance();
if (segments > 1 && threadPool && !threadPool->contains(QThread::currentThread())) {
QSemaphore semaphore;
int y = 0;
diff --git a/src/gui/painting/qimagescale_neon.cpp b/src/gui/painting/qimagescale_neon.cpp
index c8d364d56c..074b819862 100644
--- a/src/gui/painting/qimagescale_neon.cpp
+++ b/src/gui/painting/qimagescale_neon.cpp
@@ -6,8 +6,9 @@
#include <private/qsimd_p.h>
#if QT_CONFIG(thread) && !defined(Q_OS_WASM)
-#include "qsemaphore.h"
-#include "qthreadpool.h"
+#include <qsemaphore.h>
+#include <qthreadpool.h>
+#include <private/qthreadpool_p.h>
#endif
#if defined(__ARM_NEON__)
@@ -22,7 +23,7 @@ static inline void multithread_pixels_function(QImageScaleInfo *isi, int dh, con
#if QT_CONFIG(thread) && !defined(Q_OS_WASM)
int segments = (qsizetype(isi->sh) * isi->sw) / (1<<16);
segments = std::min(segments, dh);
- QThreadPool *threadPool = QThreadPool::globalInstance();
+ QThreadPool *threadPool = QThreadPoolPrivate::qtGuiInstance();
if (segments > 1 && threadPool && !threadPool->contains(QThread::currentThread())) {
QSemaphore semaphore;
int y = 0;
diff --git a/src/gui/painting/qimagescale_sse4.cpp b/src/gui/painting/qimagescale_sse4.cpp
index f55290b46c..982e533a32 100644
--- a/src/gui/painting/qimagescale_sse4.cpp
+++ b/src/gui/painting/qimagescale_sse4.cpp
@@ -7,8 +7,9 @@
#include <private/qsimd_p.h>
#if QT_CONFIG(thread) && !defined(Q_OS_WASM)
-#include "qsemaphore.h"
-#include "qthreadpool.h"
+#include <qsemaphore.h>
+#include <qthreadpool.h>
+#include <private/qthreadpool_p.h>
#endif
#if defined(QT_COMPILER_SUPPORTS_SSE4_1)
@@ -23,7 +24,7 @@ static inline void multithread_pixels_function(QImageScaleInfo *isi, int dh, con
#if QT_CONFIG(thread) && !defined(Q_OS_WASM)
int segments = (qsizetype(isi->sh) * isi->sw) / (1<<16);
segments = std::min(segments, dh);
- QThreadPool *threadPool = QThreadPool::globalInstance();
+ QThreadPool *threadPool = QThreadPoolPrivate::qtGuiInstance();
if (segments > 1 && threadPool && !threadPool->contains(QThread::currentThread())) {
QSemaphore semaphore;
int y = 0;