1 /**************************************************************************** 2 ** 3 ** Copyright (C) 2016 The Qt Company Ltd. 4 ** Contact: https://www.qt.io/licensing/ 5 ** 6 ** This file is part of the QtCore module of the Qt Toolkit. 7 ** 8 ** $QT_BEGIN_LICENSE:LGPL$ 9 ** Commercial License Usage 10 ** Licensees holding valid commercial Qt licenses may use this file in 11 ** accordance with the commercial license agreement provided with the 12 ** Software or, alternatively, in accordance with the terms contained in 13 ** a written agreement between you and The Qt Company. For licensing terms 14 ** and conditions see https://www.qt.io/terms-conditions. For further 15 ** information use the contact form at https://www.qt.io/contact-us. 16 ** 17 ** GNU Lesser General Public License Usage 18 ** Alternatively, this file may be used under the terms of the GNU Lesser 19 ** General Public License version 3 as published by the Free Software 20 ** Foundation and appearing in the file LICENSE.LGPL3 included in the 21 ** packaging of this file. Please review the following information to 22 ** ensure the GNU Lesser General Public License version 3 requirements 23 ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. 24 ** 25 ** GNU General Public License Usage 26 ** Alternatively, this file may be used under the terms of the GNU 27 ** General Public License version 2.0 or (at your option) the GNU General 28 ** Public license version 3 or any later version approved by the KDE Free 29 ** Qt Foundation. The licenses are as published by the Free Software 30 ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 31 ** included in the packaging of this file. Please review the following 32 ** information to ensure the GNU General Public License requirements will 33 ** be met: https://www.gnu.org/licenses/gpl-2.0.html and 34 ** https://www.gnu.org/licenses/gpl-3.0.html. 35 ** 36 ** $QT_END_LICENSE$ 37 ** 38 ****************************************************************************/ 39 40 #ifndef QFUTUREINTERFACE_P_H 41 #define QFUTUREINTERFACE_P_H 42 43 // 44 // W A R N I N G 45 // ------------- 46 // 47 // This file is not part of the Qt API. It exists purely as an 48 // implementation detail. This header file may change from version to 49 // version without notice, or even be removed. 50 // 51 // We mean it. 52 // 53 54 #include <QtCore/private/qglobal_p.h> 55 #include <QtCore/qelapsedtimer.h> 56 #include <QtCore/qcoreevent.h> 57 #include <QtCore/qlist.h> 58 #include <QtCore/qwaitcondition.h> 59 #include <QtCore/qrunnable.h> 60 #include <QtCore/qthreadpool.h> 61 62 QT_REQUIRE_CONFIG(future); 63 64 QT_BEGIN_NAMESPACE 65 66 class QFutureCallOutEvent : public QEvent 67 { 68 public: 69 enum CallOutType { 70 Started, 71 Finished, 72 Canceled, 73 Paused, 74 Resumed, 75 Progress, 76 ProgressRange, 77 ResultsReady 78 }; 79 QFutureCallOutEvent()80 QFutureCallOutEvent() 81 : QEvent(QEvent::FutureCallOut), callOutType(CallOutType(0)), index1(-1), index2(-1) 82 { } 83 explicit QFutureCallOutEvent(CallOutType callOutType, int index1 = -1) QEvent(QEvent::FutureCallOut)84 : QEvent(QEvent::FutureCallOut), callOutType(callOutType), index1(index1), index2(-1) 85 { } QFutureCallOutEvent(CallOutType callOutType,int index1,int index2)86 QFutureCallOutEvent(CallOutType callOutType, int index1, int index2) 87 : QEvent(QEvent::FutureCallOut), callOutType(callOutType), index1(index1), index2(index2) 88 { } 89 QFutureCallOutEvent(CallOutType callOutType,int index1,const QString & text)90 QFutureCallOutEvent(CallOutType callOutType, int index1, const QString &text) 91 : QEvent(QEvent::FutureCallOut), 92 callOutType(callOutType), 93 index1(index1), 94 index2(-1), 95 text(text) 96 { } 97 98 CallOutType callOutType; 99 int index1; 100 int index2; 101 QString text; 102 clone()103 QFutureCallOutEvent *clone() const 104 { 105 return new QFutureCallOutEvent(callOutType, index1, index2, text); 106 } 107 108 private: QFutureCallOutEvent(CallOutType callOutType,int index1,int index2,const QString & text)109 QFutureCallOutEvent(CallOutType callOutType, 110 int index1, 111 int index2, 112 const QString &text) 113 : QEvent(QEvent::FutureCallOut), 114 callOutType(callOutType), 115 index1(index1), 116 index2(index2), 117 text(text) 118 { } 119 }; 120 121 class QFutureCallOutInterface 122 { 123 public: ~QFutureCallOutInterface()124 virtual ~QFutureCallOutInterface() {} 125 virtual void postCallOutEvent(const QFutureCallOutEvent &) = 0; 126 virtual void callOutInterfaceDisconnected() = 0; 127 }; 128 129 class QFutureInterfaceBasePrivate 130 { 131 public: 132 QFutureInterfaceBasePrivate(QFutureInterfaceBase::State initialState); 133 134 // When the last QFuture<T> reference is removed, we need to make 135 // sure that data stored in the ResultStore is cleaned out. 136 // Since QFutureInterfaceBasePrivate can be shared between QFuture<T> 137 // and QFuture<void> objects, we use a separate ref. counter 138 // to keep track of QFuture<T> objects. 139 class RefCount 140 { 141 public: 142 inline RefCount(int r = 0, int rt = 0) m_refCount(r)143 : m_refCount(r), m_refCountT(rt) {} 144 // Default ref counter for QFIBP ref()145 inline bool ref() { return m_refCount.ref(); } deref()146 inline bool deref() { return m_refCount.deref(); } load()147 inline int load() const { return m_refCount.loadRelaxed(); } 148 // Ref counter for type T refT()149 inline bool refT() { return m_refCountT.ref(); } derefT()150 inline bool derefT() { return m_refCountT.deref(); } loadT()151 inline int loadT() const { return m_refCountT.loadRelaxed(); } 152 153 private: 154 QAtomicInt m_refCount; 155 QAtomicInt m_refCountT; 156 }; 157 158 // T: accessed from executing thread 159 // Q: accessed from the waiting/querying thread 160 RefCount refCount; 161 mutable QMutex m_mutex; 162 QWaitCondition waitCondition; 163 QList<QFutureCallOutInterface *> outputConnections; 164 int m_progressValue; // TQ 165 int m_progressMinimum; // TQ 166 int m_progressMaximum; // TQ 167 QAtomicInt state; // reads and writes can happen unprotected, both must be atomic 168 QElapsedTimer progressTime; 169 QWaitCondition pausedWaitCondition; 170 QtPrivate::ResultStoreBase m_results; 171 bool manualProgress; // only accessed from executing thread 172 int m_expectedResultCount; 173 QtPrivate::ExceptionStore m_exceptionStore; 174 QString m_progressText; 175 QRunnable *runnable; 176 QThreadPool *m_pool; 177 pool()178 inline QThreadPool *pool() const 179 { return m_pool ? m_pool : QThreadPool::globalInstance(); } 180 181 // Internal functions that does not change the mutex state. 182 // The mutex must be locked when calling these. 183 int internal_resultCount() const; 184 bool internal_isResultReadyAt(int index) const; 185 bool internal_waitForNextResult(); 186 bool internal_updateProgress(int progress, const QString &progressText = QString()); 187 void internal_setThrottled(bool enable); 188 void sendCallOut(const QFutureCallOutEvent &callOut); 189 void sendCallOuts(const QFutureCallOutEvent &callOut1, const QFutureCallOutEvent &callOut2); 190 void connectOutputInterface(QFutureCallOutInterface *iface); 191 void disconnectOutputInterface(QFutureCallOutInterface *iface); 192 193 void setState(QFutureInterfaceBase::State state); 194 }; 195 196 QT_END_NAMESPACE 197 198 #endif 199