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