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>
|
#include <private/qthread_p.h>
|
||||||
#if QT_CONFIG(thread)
|
#if QT_CONFIG(thread)
|
||||||
#include <qthreadpool.h>
|
#include <qthreadpool.h>
|
||||||
|
#include <private/qthreadpool_p.h>
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
#include <qelapsedtimer.h>
|
#include <qelapsedtimer.h>
|
||||||
@ -907,8 +908,10 @@ QCoreApplication::~QCoreApplication()
|
|||||||
#if QT_CONFIG(thread)
|
#if QT_CONFIG(thread)
|
||||||
// Synchronize and stop the global thread pool threads.
|
// Synchronize and stop the global thread pool threads.
|
||||||
QThreadPool *globalThreadPool = nullptr;
|
QThreadPool *globalThreadPool = nullptr;
|
||||||
|
QThreadPool *guiThreadPool = nullptr;
|
||||||
QT_TRY {
|
QT_TRY {
|
||||||
globalThreadPool = QThreadPool::globalInstance();
|
globalThreadPool = QThreadPool::globalInstance();
|
||||||
|
guiThreadPool = QThreadPoolPrivate::qtGuiInstance();
|
||||||
} QT_CATCH (...) {
|
} QT_CATCH (...) {
|
||||||
// swallow the exception, since destructors shouldn't throw
|
// swallow the exception, since destructors shouldn't throw
|
||||||
}
|
}
|
||||||
@ -916,6 +919,10 @@ QCoreApplication::~QCoreApplication()
|
|||||||
globalThreadPool->waitForDone();
|
globalThreadPool->waitForDone();
|
||||||
delete globalThreadPool;
|
delete globalThreadPool;
|
||||||
}
|
}
|
||||||
|
if (guiThreadPool) {
|
||||||
|
guiThreadPool->waitForDone();
|
||||||
|
delete guiThreadPool;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef QT_NO_QOBJECT
|
#ifndef QT_NO_QOBJECT
|
||||||
|
@ -474,6 +474,21 @@ QThreadPool *QThreadPool::globalInstance()
|
|||||||
return theInstance;
|
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
|
Reserves a thread and uses it to run \a runnable, unless this thread will
|
||||||
make the current thread count exceed maxThreadCount(). In that case,
|
make the current thread count exceed maxThreadCount(). In that case,
|
||||||
|
@ -134,6 +134,8 @@ public:
|
|||||||
void stealAndRunRunnable(QRunnable *runnable);
|
void stealAndRunRunnable(QRunnable *runnable);
|
||||||
void deletePageIfFinished(QueuePage *page);
|
void deletePageIfFinished(QueuePage *page);
|
||||||
|
|
||||||
|
static QThreadPool *qtGuiInstance();
|
||||||
|
|
||||||
mutable QMutex mutex;
|
mutable QMutex mutex;
|
||||||
QSet<QThreadPoolThread *> allThreads;
|
QSet<QThreadPoolThread *> allThreads;
|
||||||
QQueue<QThreadPoolThread *> waitingThreads;
|
QQueue<QThreadPoolThread *> waitingThreads;
|
||||||
|
@ -35,8 +35,9 @@
|
|||||||
#include <private/qfont_p.h>
|
#include <private/qfont_p.h>
|
||||||
|
|
||||||
#if QT_CONFIG(thread)
|
#if QT_CONFIG(thread)
|
||||||
#include "qsemaphore.h"
|
#include <qsemaphore.h>
|
||||||
#include "qthreadpool.h"
|
#include <qthreadpool.h>
|
||||||
|
#include <private/qthreadpool_p.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <qtgui_tracepoints_p.h>
|
#include <qtgui_tracepoints_p.h>
|
||||||
@ -5119,7 +5120,7 @@ void QImage::applyColorTransform(const QColorTransform &transform)
|
|||||||
#if QT_CONFIG(thread) && !defined(Q_OS_WASM)
|
#if QT_CONFIG(thread) && !defined(Q_OS_WASM)
|
||||||
int segments = (qsizetype(width()) * height()) >> 16;
|
int segments = (qsizetype(width()) * height()) >> 16;
|
||||||
segments = std::min(segments, height());
|
segments = std::min(segments, height());
|
||||||
QThreadPool *threadPool = QThreadPool::globalInstance();
|
QThreadPool *threadPool = QThreadPoolPrivate::qtGuiInstance();
|
||||||
if (segments > 1 && threadPool && !threadPool->contains(QThread::currentThread())) {
|
if (segments > 1 && threadPool && !threadPool->contains(QThread::currentThread())) {
|
||||||
QSemaphore semaphore;
|
QSemaphore semaphore;
|
||||||
int y = 0;
|
int y = 0;
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
#if QT_CONFIG(thread)
|
#if QT_CONFIG(thread)
|
||||||
#include <qsemaphore.h>
|
#include <qsemaphore.h>
|
||||||
#include <qthreadpool.h>
|
#include <qthreadpool.h>
|
||||||
|
#include <private/qthreadpool_p.h>
|
||||||
#ifdef Q_OS_WASM
|
#ifdef Q_OS_WASM
|
||||||
// WebAssembly has threads; however we can't block the main thread.
|
// WebAssembly has threads; however we can't block the main thread.
|
||||||
#else
|
#else
|
||||||
@ -203,7 +204,7 @@ void convert_generic(QImageData *dest, const QImageData *src, Qt::ImageConversio
|
|||||||
int segments = (qsizetype(src->width) * src->height) >> 16;
|
int segments = (qsizetype(src->width) * src->height) >> 16;
|
||||||
segments = std::min(segments, src->height);
|
segments = std::min(segments, src->height);
|
||||||
|
|
||||||
QThreadPool *threadPool = QThreadPool::globalInstance();
|
QThreadPool *threadPool = QThreadPoolPrivate::qtGuiInstance();
|
||||||
if (segments <= 1 || !threadPool || threadPool->contains(QThread::currentThread()))
|
if (segments <= 1 || !threadPool || threadPool->contains(QThread::currentThread()))
|
||||||
return convertSegment(0, src->height);
|
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;
|
int segments = (qsizetype(src->width) * src->height) >> 16;
|
||||||
segments = std::min(segments, src->height);
|
segments = std::min(segments, src->height);
|
||||||
|
|
||||||
QThreadPool *threadPool = QThreadPool::globalInstance();
|
QThreadPool *threadPool = QThreadPoolPrivate::qtGuiInstance();
|
||||||
if (segments <= 1 || !threadPool || threadPool->contains(QThread::currentThread()))
|
if (segments <= 1 || !threadPool || threadPool->contains(QThread::currentThread()))
|
||||||
return convertSegment(0, src->height);
|
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;
|
int segments = (qsizetype(src->width) * src->height) >> 16;
|
||||||
segments = std::min(segments, src->height);
|
segments = std::min(segments, src->height);
|
||||||
|
|
||||||
QThreadPool *threadPool = QThreadPool::globalInstance();
|
QThreadPool *threadPool = QThreadPoolPrivate::qtGuiInstance();
|
||||||
if (segments <= 1 || !threadPool || threadPool->contains(QThread::currentThread()))
|
if (segments <= 1 || !threadPool || threadPool->contains(QThread::currentThread()))
|
||||||
return convertSegment(0, src->height);
|
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
|
#ifdef QT_USE_THREAD_PARALLEL_IMAGE_CONVERSIONS
|
||||||
int segments = (qsizetype(data->width) * data->height) >> 16;
|
int segments = (qsizetype(data->width) * data->height) >> 16;
|
||||||
segments = std::min(segments, data->height);
|
segments = std::min(segments, data->height);
|
||||||
QThreadPool *threadPool = QThreadPool::globalInstance();
|
QThreadPool *threadPool = QThreadPoolPrivate::qtGuiInstance();
|
||||||
if (segments > 1 && threadPool && !threadPool->contains(QThread::currentThread())) {
|
if (segments > 1 && threadPool && !threadPool->contains(QThread::currentThread())) {
|
||||||
QSemaphore semaphore;
|
QSemaphore semaphore;
|
||||||
int y = 0;
|
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
|
#ifdef QT_USE_THREAD_PARALLEL_IMAGE_CONVERSIONS
|
||||||
int segments = (qsizetype(data->width) * data->height) >> 16;
|
int segments = (qsizetype(data->width) * data->height) >> 16;
|
||||||
segments = std::min(segments, data->height);
|
segments = std::min(segments, data->height);
|
||||||
QThreadPool *threadPool = QThreadPool::globalInstance();
|
QThreadPool *threadPool = QThreadPoolPrivate::qtGuiInstance();
|
||||||
if (segments > 1 && threadPool && !threadPool->contains(QThread::currentThread())) {
|
if (segments > 1 && threadPool && !threadPool->contains(QThread::currentThread())) {
|
||||||
QSemaphore semaphore;
|
QSemaphore semaphore;
|
||||||
int y = 0;
|
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
|
#ifdef QT_USE_THREAD_PARALLEL_IMAGE_CONVERSIONS
|
||||||
int segments = (qsizetype(data->width) * data->height) >> 16;
|
int segments = (qsizetype(data->width) * data->height) >> 16;
|
||||||
segments = std::min(segments, data->height);
|
segments = std::min(segments, data->height);
|
||||||
QThreadPool *threadPool = QThreadPool::globalInstance();
|
QThreadPool *threadPool = QThreadPoolPrivate::qtGuiInstance();
|
||||||
if (segments > 1 && threadPool && !threadPool->contains(QThread::currentThread())) {
|
if (segments > 1 && threadPool && !threadPool->contains(QThread::currentThread())) {
|
||||||
QSemaphore semaphore;
|
QSemaphore semaphore;
|
||||||
int y = 0;
|
int y = 0;
|
||||||
|
@ -32,6 +32,7 @@
|
|||||||
#if defined(QT_USE_THREAD_PARALLEL_FILLS)
|
#if defined(QT_USE_THREAD_PARALLEL_FILLS)
|
||||||
#include <qsemaphore.h>
|
#include <qsemaphore.h>
|
||||||
#include <qthreadpool.h>
|
#include <qthreadpool.h>
|
||||||
|
#include <private/qthreadpool_p.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
@ -3777,7 +3778,7 @@ static void spanfill_from_first(QRasterBuffer *rasterBuffer, QPixelLayout::BPP b
|
|||||||
#if defined(QT_USE_THREAD_PARALLEL_FILLS)
|
#if defined(QT_USE_THREAD_PARALLEL_FILLS)
|
||||||
#define QT_THREAD_PARALLEL_FILLS(function) \
|
#define QT_THREAD_PARALLEL_FILLS(function) \
|
||||||
const int segments = (count + 32) / 64; \
|
const int segments = (count + 32) / 64; \
|
||||||
QThreadPool *threadPool = QThreadPool::globalInstance(); \
|
QThreadPool *threadPool = QThreadPoolPrivate::qtGuiInstance(); \
|
||||||
if (segments > 1 && threadPool && !threadPool->contains(QThread::currentThread())) { \
|
if (segments > 1 && threadPool && !threadPool->contains(QThread::currentThread())) { \
|
||||||
QSemaphore semaphore; \
|
QSemaphore semaphore; \
|
||||||
int c = 0; \
|
int c = 0; \
|
||||||
@ -3786,7 +3787,7 @@ static void spanfill_from_first(QRasterBuffer *rasterBuffer, QPixelLayout::BPP b
|
|||||||
threadPool->start([&, c, cn]() { \
|
threadPool->start([&, c, cn]() { \
|
||||||
function(c, c + cn); \
|
function(c, c + cn); \
|
||||||
semaphore.release(1); \
|
semaphore.release(1); \
|
||||||
}); \
|
}, 1); \
|
||||||
c += cn; \
|
c += cn; \
|
||||||
} \
|
} \
|
||||||
semaphore.acquire(segments); \
|
semaphore.acquire(segments); \
|
||||||
|
@ -10,8 +10,9 @@
|
|||||||
#include "qrgbafloat.h"
|
#include "qrgbafloat.h"
|
||||||
|
|
||||||
#if QT_CONFIG(thread) && !defined(Q_OS_WASM)
|
#if QT_CONFIG(thread) && !defined(Q_OS_WASM)
|
||||||
#include "qsemaphore.h"
|
#include <qsemaphore.h>
|
||||||
#include "qthreadpool.h"
|
#include <qthreadpool.h>
|
||||||
|
#include <private/qthreadpool_p.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
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)
|
#if QT_CONFIG(thread) && !defined(Q_OS_WASM)
|
||||||
int segments = (qsizetype(isi->sh) * isi->sw) / (1<<16);
|
int segments = (qsizetype(isi->sh) * isi->sw) / (1<<16);
|
||||||
segments = std::min(segments, dh);
|
segments = std::min(segments, dh);
|
||||||
QThreadPool *threadPool = QThreadPool::globalInstance();
|
QThreadPool *threadPool = QThreadPoolPrivate::qtGuiInstance();
|
||||||
if (segments > 1 && threadPool && !threadPool->contains(QThread::currentThread())) {
|
if (segments > 1 && threadPool && !threadPool->contains(QThread::currentThread())) {
|
||||||
QSemaphore semaphore;
|
QSemaphore semaphore;
|
||||||
int y = 0;
|
int y = 0;
|
||||||
|
@ -6,8 +6,9 @@
|
|||||||
#include <private/qsimd_p.h>
|
#include <private/qsimd_p.h>
|
||||||
|
|
||||||
#if QT_CONFIG(thread) && !defined(Q_OS_WASM)
|
#if QT_CONFIG(thread) && !defined(Q_OS_WASM)
|
||||||
#include "qsemaphore.h"
|
#include <qsemaphore.h>
|
||||||
#include "qthreadpool.h"
|
#include <qthreadpool.h>
|
||||||
|
#include <private/qthreadpool_p.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(__ARM_NEON__)
|
#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)
|
#if QT_CONFIG(thread) && !defined(Q_OS_WASM)
|
||||||
int segments = (qsizetype(isi->sh) * isi->sw) / (1<<16);
|
int segments = (qsizetype(isi->sh) * isi->sw) / (1<<16);
|
||||||
segments = std::min(segments, dh);
|
segments = std::min(segments, dh);
|
||||||
QThreadPool *threadPool = QThreadPool::globalInstance();
|
QThreadPool *threadPool = QThreadPoolPrivate::qtGuiInstance();
|
||||||
if (segments > 1 && threadPool && !threadPool->contains(QThread::currentThread())) {
|
if (segments > 1 && threadPool && !threadPool->contains(QThread::currentThread())) {
|
||||||
QSemaphore semaphore;
|
QSemaphore semaphore;
|
||||||
int y = 0;
|
int y = 0;
|
||||||
|
@ -7,8 +7,9 @@
|
|||||||
#include <private/qsimd_p.h>
|
#include <private/qsimd_p.h>
|
||||||
|
|
||||||
#if QT_CONFIG(thread) && !defined(Q_OS_WASM)
|
#if QT_CONFIG(thread) && !defined(Q_OS_WASM)
|
||||||
#include "qsemaphore.h"
|
#include <qsemaphore.h>
|
||||||
#include "qthreadpool.h"
|
#include <qthreadpool.h>
|
||||||
|
#include <private/qthreadpool_p.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(QT_COMPILER_SUPPORTS_SSE4_1)
|
#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)
|
#if QT_CONFIG(thread) && !defined(Q_OS_WASM)
|
||||||
int segments = (qsizetype(isi->sh) * isi->sw) / (1<<16);
|
int segments = (qsizetype(isi->sh) * isi->sw) / (1<<16);
|
||||||
segments = std::min(segments, dh);
|
segments = std::min(segments, dh);
|
||||||
QThreadPool *threadPool = QThreadPool::globalInstance();
|
QThreadPool *threadPool = QThreadPoolPrivate::qtGuiInstance();
|
||||||
if (segments > 1 && threadPool && !threadPool->contains(QThread::currentThread())) {
|
if (segments > 1 && threadPool && !threadPool->contains(QThread::currentThread())) {
|
||||||
QSemaphore semaphore;
|
QSemaphore semaphore;
|
||||||
int y = 0;
|
int y = 0;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user