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>
This commit is contained in:
parent
c1c201025e
commit
61b8e334d2
@ -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>
|
||||
@ -907,8 +908,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
|
||||
}
|
||||
@ -916,6 +919,10 @@ QCoreApplication::~QCoreApplication()
|
||||
globalThreadPool->waitForDone();
|
||||
delete globalThreadPool;
|
||||
}
|
||||
if (guiThreadPool) {
|
||||
guiThreadPool->waitForDone();
|
||||
delete guiThreadPool;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef QT_NO_QOBJECT
|
||||
|
@ -474,6 +474,21 @@ QThreadPool *QThreadPool::globalInstance()
|
||||
return theInstance;
|
||||
}
|
||||
|
||||
/*!
|
||||
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,
|
||||
|
@ -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;
|
||||
|
@ -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>
|
||||
@ -5119,7 +5120,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;
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
@ -3777,7 +3778,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; \
|
||||
@ -3786,7 +3787,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); \
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user