1 /* 2 SPDX-FileCopyrightText: 2010 David Nolden <david.nolden.kdevelop@art-master.de> 3 4 SPDX-License-Identifier: GPL-2.0-or-later 5 */ 6 7 #ifndef KDEVPLATFORM_FOREGROUNDLOCK_H 8 #define KDEVPLATFORM_FOREGROUNDLOCK_H 9 10 #include "utilexport.h" 11 #include <QObject> 12 #include <QMutex> 13 #include <QWaitCondition> 14 15 namespace KDevelop { 16 17 /** 18 * A locking object that locks the resources that are associated to the main thread. When this lock is held, 19 * you can call any thread-unsafe functions, because the foreground thread is locked in an event. 20 * 21 * The lock always becomes available when the foreground thread stops processing events. 22 * 23 * @warning There is one simple rule you must always follow to prevent deadlocks: 24 * @em Never lock anything before locking the foreground mutex!! 25 * That also means that you must not take this lock in contexts where 26 * you don't know what other mutexes might be locked. 27 * 28 * @warning Objects that have QObject as base always get the thread they were created in assigned (see thread affinity, QObject::moveToThread), 29 * which seriously affects the objects functionality regarding signals/slots. 30 * The foreground lock does not change the thread affinity, so holding the foreground lock does not fully equal being in the foreground. 31 * It may generally be unsafe to call foreground functions that create QObjects from within the background. 32 */ 33 class KDEVPLATFORMUTIL_EXPORT ForegroundLock 34 { 35 public: 36 explicit ForegroundLock(bool lock = true); 37 ~ForegroundLock(); 38 ForegroundLock(const ForegroundLock& rhs) = delete; 39 ForegroundLock& operator=(const ForegroundLock& rhs) = delete; 40 41 void unlock(); 42 void relock(); 43 bool tryLock(); 44 45 /// Returns whether the current thread holds the foreground lock 46 static bool isLockedForThread(); 47 48 bool isLocked() const; 49 50 private: 51 bool m_locked = false; 52 }; 53 54 /** 55 * Use this object if you want to temporarily release the foreground lock, 56 * for example when sleeping in the foreground thread, or when waiting in the foreground 57 * thread for a background thread which should get the chance to lock the foreground. 58 * 59 * While this object is alive, you _must not_ access any non-threadsafe resources 60 * that belong to the foreground, and you must not start an event-loop. 61 */ 62 class KDEVPLATFORMUTIL_EXPORT TemporarilyReleaseForegroundLock 63 { 64 public: 65 TemporarilyReleaseForegroundLock(); 66 ~TemporarilyReleaseForegroundLock(); 67 68 private: 69 TemporarilyReleaseForegroundLock(const TemporarilyReleaseForegroundLock&); 70 TemporarilyReleaseForegroundLock& operator=(const TemporarilyReleaseForegroundLock& rhs); 71 int m_recursion; 72 }; 73 74 #define VERIFY_FOREGROUND_LOCKED Q_ASSERT(KDevelop::ForegroundLock::isLockedForThread()); 75 76 class KDEVPLATFORMUTIL_EXPORT DoInForeground : public QObject 77 { 78 Q_OBJECT 79 80 public: 81 DoInForeground(); 82 ~DoInForeground() override; 83 84 void doIt(); 85 86 private Q_SLOTS: 87 void doInternalSlot(); 88 89 private: 90 virtual void doInternal() = 0; 91 QMutex m_mutex; 92 QWaitCondition m_wait; 93 }; 94 95 } 96 97 #endif 98