File indexing completed on 2024-05-12 15:58:25
0001 /* 0002 * SPDX-FileCopyrightText: 2011 Dmitry Kazakov <dimula73@gmail.com> 0003 * 0004 * SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 #ifndef __KIS_LAZY_WAIT_CONDITION_H 0008 #define __KIS_LAZY_WAIT_CONDITION_H 0009 0010 0011 #include <QWaitCondition> 0012 0013 /** 0014 * This class is used for catching a particular condition met. 0015 * We call it "lazy", because the decision about the condition is made 0016 * by the waiting thread itself. The other thread, "wakingup" one, 0017 * just points the former one the moments of time when the condition 0018 * *might* have been satisfied. This creates some limitations for 0019 * the condition (see a note in the end of the text). 0020 * 0021 * Usage pattern: 0022 * 0023 * Waiting thread: 0024 * 0025 * KisLazyWaitCondition condition; 0026 * condition.initWainting(); // (1) 0027 * while(!checkSatisfied()) { 0028 * condition.wait(); 0029 * } 0030 * condition.endWaiting(); // (2) 0031 * 0032 * 0033 * Wakingup thread: 0034 * 0035 * if(checkMightSatisfied()) { 0036 * condition.wakeAll(); 0037 * } 0038 * 0039 * If the condition is met and reported, it is guaranteed that 0040 * all the threads, those are currently running between 0041 * lines (1) and (2) will be waken up and leave the loop. 0042 * 0043 * NOTE: 0044 * The condition checkSatisfied() must not change it's state, until 0045 * all the waiting threads leave the waiting loop. This requirement 0046 * must be guaranteed by the user of this class 0047 */ 0048 0049 class KisLazyWaitCondition 0050 { 0051 public: 0052 KisLazyWaitCondition() 0053 : m_waitCounter(0), 0054 m_wakeupCounter(0) 0055 { 0056 } 0057 0058 void initWaiting() { 0059 QMutexLocker locker(&m_mutex); 0060 if(!m_waitCounter) { 0061 m_wakeupCounter = 0; 0062 } 0063 0064 m_waitCounter++; 0065 } 0066 0067 void endWaiting() { 0068 QMutexLocker locker(&m_mutex); 0069 m_waitCounter--; 0070 } 0071 0072 bool wait(unsigned long time = ULONG_MAX) { 0073 QMutexLocker locker(&m_mutex); 0074 bool result = true; 0075 if(!m_wakeupCounter) { 0076 result = m_condition.wait(&m_mutex, time); 0077 } 0078 if(result) { 0079 m_wakeupCounter--; 0080 } 0081 return result; 0082 } 0083 0084 void wakeAll() { 0085 if(!m_waitCounter) return; 0086 0087 QMutexLocker locker(&m_mutex); 0088 if(m_waitCounter) { 0089 m_wakeupCounter += m_waitCounter; 0090 m_condition.wakeAll(); 0091 } 0092 } 0093 0094 bool isSomeoneWaiting() { 0095 return m_waitCounter; 0096 } 0097 0098 private: 0099 QMutex m_mutex; 0100 QWaitCondition m_condition; 0101 volatile int m_waitCounter; 0102 int m_wakeupCounter; 0103 }; 0104 0105 #endif /* __KIS_LAZY_WAIT_CONDITION_H */