diff options
author | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2023-02-24 10:57:56 +0100 |
---|---|---|
committer | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2023-03-02 11:11:09 +0000 |
commit | e6b53d5e4bbc4cf9c3dd92db3506d240a119764e (patch) | |
tree | 97a3c72a5dee02ea5dbb8142f225490e6d4d84a7 /src | |
parent | 7f8020f1f7177d8f3a626e0b746f07dd7727b7e6 (diff) | |
download | qtbase-e6b53d5e4bbc4cf9c3dd92db3506d240a119764e.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)
Diffstat (limited to 'src')
-rw-r--r-- | src/corelib/kernel/qcoreapplication.cpp | 7 | ||||
-rw-r--r-- | src/corelib/thread/qthreadpool.cpp | 15 | ||||
-rw-r--r-- | src/corelib/thread/qthreadpool_p.h | 2 | ||||
-rw-r--r-- | src/gui/image/qimage.cpp | 7 | ||||
-rw-r--r-- | src/gui/image/qimage_conversions.cpp | 13 | ||||
-rw-r--r-- | src/gui/painting/qdrawhelper.cpp | 5 | ||||
-rw-r--r-- | src/gui/painting/qimagescale.cpp | 7 | ||||
-rw-r--r-- | src/gui/painting/qimagescale_neon.cpp | 7 | ||||
-rw-r--r-- | src/gui/painting/qimagescale_sse4.cpp | 7 |
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 a8a58fd12a..9a956904f8 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; |