File indexing completed on 2024-05-05 04:38:44
0001 /* 0002 SPDX-FileCopyrightText: 2010 David Nolden <david.nolden.kdevelop@art-master.de> 0003 0004 SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 #ifndef KDEVPLATFORM_FOREGROUNDLOCK_H 0008 #define KDEVPLATFORM_FOREGROUNDLOCK_H 0009 0010 #include "utilexport.h" 0011 #include <QObject> 0012 #include <QMutex> 0013 #include <QWaitCondition> 0014 0015 namespace KDevelop { 0016 0017 /** 0018 * A locking object that locks the resources that are associated to the main thread. When this lock is held, 0019 * you can call any thread-unsafe functions, because the foreground thread is locked in an event. 0020 * 0021 * The lock always becomes available when the foreground thread stops processing events. 0022 * 0023 * @warning There is one simple rule you must always follow to prevent deadlocks: 0024 * @em Never lock anything before locking the foreground mutex!! 0025 * That also means that you must not take this lock in contexts where 0026 * you don't know what other mutexes might be locked. 0027 * 0028 * @warning Objects that have QObject as base always get the thread they were created in assigned (see thread affinity, QObject::moveToThread), 0029 * which seriously affects the objects functionality regarding signals/slots. 0030 * The foreground lock does not change the thread affinity, so holding the foreground lock does not fully equal being in the foreground. 0031 * It may generally be unsafe to call foreground functions that create QObjects from within the background. 0032 */ 0033 class KDEVPLATFORMUTIL_EXPORT ForegroundLock 0034 { 0035 public: 0036 explicit ForegroundLock(bool lock = true); 0037 ~ForegroundLock(); 0038 ForegroundLock(const ForegroundLock& rhs) = delete; 0039 ForegroundLock& operator=(const ForegroundLock& rhs) = delete; 0040 0041 void unlock(); 0042 void relock(); 0043 bool tryLock(); 0044 0045 /// Returns whether the current thread holds the foreground lock 0046 static bool isLockedForThread(); 0047 0048 bool isLocked() const; 0049 0050 private: 0051 bool m_locked = false; 0052 }; 0053 0054 /** 0055 * Use this object if you want to temporarily release the foreground lock, 0056 * for example when sleeping in the foreground thread, or when waiting in the foreground 0057 * thread for a background thread which should get the chance to lock the foreground. 0058 * 0059 * While this object is alive, you _must not_ access any non-threadsafe resources 0060 * that belong to the foreground, and you must not start an event-loop. 0061 */ 0062 class KDEVPLATFORMUTIL_EXPORT TemporarilyReleaseForegroundLock 0063 { 0064 public: 0065 TemporarilyReleaseForegroundLock(); 0066 ~TemporarilyReleaseForegroundLock(); 0067 0068 private: 0069 TemporarilyReleaseForegroundLock(const TemporarilyReleaseForegroundLock&); 0070 TemporarilyReleaseForegroundLock& operator=(const TemporarilyReleaseForegroundLock& rhs); 0071 int m_recursion; 0072 }; 0073 0074 #define VERIFY_FOREGROUND_LOCKED Q_ASSERT(KDevelop::ForegroundLock::isLockedForThread()); 0075 0076 class KDEVPLATFORMUTIL_EXPORT DoInForeground : public QObject 0077 { 0078 Q_OBJECT 0079 0080 public: 0081 DoInForeground(); 0082 ~DoInForeground() override; 0083 0084 void doIt(); 0085 0086 private Q_SLOTS: 0087 void doInternalSlot(); 0088 0089 private: 0090 virtual void doInternal() = 0; 0091 QMutex m_mutex; 0092 QWaitCondition m_wait; 0093 }; 0094 0095 } 0096 0097 #endif