File indexing completed on 2024-05-12 15:58:50
0001 /* 0002 * SPDX-FileCopyrightText: 2020 Dmitry Kazakov <dimula73@gmail.com> 0003 * 0004 * SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 #include "KisBusyWaitBroker.h" 0007 0008 #include <QGlobalStatic> 0009 #include <QMutex> 0010 #include <QMutexLocker> 0011 0012 #include <QThread> 0013 #include <QApplication> 0014 0015 #include "kis_image.h" 0016 0017 0018 Q_GLOBAL_STATIC(KisBusyWaitBroker, s_instance) 0019 0020 0021 struct KisBusyWaitBroker::Private 0022 { 0023 QMutex lock; 0024 QHash<KisImage*, int> waitingOnImages; 0025 int guiThreadLockCount = 0; 0026 0027 std::function<void(KisImageSP)> feedbackCallback; 0028 }; 0029 0030 0031 KisBusyWaitBroker::KisBusyWaitBroker() 0032 : m_d(new Private) 0033 { 0034 } 0035 0036 KisBusyWaitBroker::~KisBusyWaitBroker() 0037 { 0038 } 0039 0040 KisBusyWaitBroker *KisBusyWaitBroker::instance() 0041 { 0042 return s_instance; 0043 } 0044 0045 void KisBusyWaitBroker::notifyWaitOnImageStarted(KisImage* image) 0046 { 0047 if (QThread::currentThread() != qApp->thread()) return; 0048 0049 bool needsStartCallback = false; 0050 0051 { 0052 QMutexLocker l(&m_d->lock); 0053 0054 m_d->guiThreadLockCount++; 0055 m_d->waitingOnImages[image]++; 0056 0057 needsStartCallback = m_d->waitingOnImages[image] == 1; 0058 } 0059 0060 if (m_d->feedbackCallback && needsStartCallback && image->refCount()) { 0061 m_d->feedbackCallback(image); 0062 } 0063 } 0064 0065 void KisBusyWaitBroker::notifyWaitOnImageEnded(KisImage* image) 0066 { 0067 if (QThread::currentThread() != qApp->thread()) return; 0068 0069 { 0070 QMutexLocker l(&m_d->lock); 0071 m_d->guiThreadLockCount--; 0072 0073 m_d->waitingOnImages[image]--; 0074 KIS_SAFE_ASSERT_RECOVER_NOOP(m_d->waitingOnImages[image] >= 0); 0075 0076 if (m_d->waitingOnImages[image] == 0) { 0077 m_d->waitingOnImages.remove(image); 0078 } 0079 } 0080 } 0081 0082 void KisBusyWaitBroker::notifyGeneralWaitStarted() 0083 { 0084 if (QThread::currentThread() != qApp->thread()) return; 0085 0086 QMutexLocker l(&m_d->lock); 0087 m_d->guiThreadLockCount++; 0088 } 0089 0090 void KisBusyWaitBroker::notifyGeneralWaitEnded() 0091 { 0092 if (QThread::currentThread() != qApp->thread()) return; 0093 0094 QMutexLocker l(&m_d->lock); 0095 m_d->guiThreadLockCount--; 0096 } 0097 0098 void KisBusyWaitBroker::setFeedbackCallback(std::function<void (KisImageSP)> callback) 0099 { 0100 m_d->feedbackCallback = callback; 0101 } 0102 0103 bool KisBusyWaitBroker::guiThreadIsWaitingForBetterWeather() const 0104 { 0105 return m_d->guiThreadLockCount; 0106 } 0107 0108