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_H
41#define QFUTUREINTERFACE_H
42
43#include <QtCore/qrunnable.h>
44#include <QtCore/qmutex.h>
45#include <QtCore/qexception.h>
46#include <QtCore/qresultstore.h>
47
48#include <mutex>
49
50QT_REQUIRE_CONFIG(future);
51
52QT_BEGIN_NAMESPACE
53
54
55template <typename T> class QFuture;
56class QThreadPool;
57class QFutureInterfaceBasePrivate;
58class QFutureWatcherBase;
59class QFutureWatcherBasePrivate;
60
61class Q_CORE_EXPORT QFutureInterfaceBase
62{
63public:
64 enum State {
65 NoState = 0x00,
66 Running = 0x01,
67 Started = 0x02,
68 Finished = 0x04,
69 Canceled = 0x08,
70 Paused = 0x10,
71 Throttled = 0x20
72 };
73
74 QFutureInterfaceBase(State initialState = NoState);
75 QFutureInterfaceBase(const QFutureInterfaceBase &other);
76 virtual ~QFutureInterfaceBase();
77
78 // reporting functions available to the engine author:
79 void reportStarted();
80 void reportFinished();
81 void reportCanceled();
82#ifndef QT_NO_EXCEPTIONS
83 void reportException(const QException &e);
84#endif
85 void reportResultsReady(int beginIndex, int endIndex);
86
87 void setRunnable(QRunnable *runnable);
88 void setThreadPool(QThreadPool *pool);
89 void setFilterMode(bool enable);
90 void setProgressRange(int minimum, int maximum);
91 int progressMinimum() const;
92 int progressMaximum() const;
93 bool isProgressUpdateNeeded() const;
94 void setProgressValue(int progressValue);
95 int progressValue() const;
96 void setProgressValueAndText(int progressValue, const QString &progressText);
97 QString progressText() const;
98
99 void setExpectedResultCount(int resultCount);
100 int expectedResultCount();
101 int resultCount() const;
102
103 bool queryState(State state) const;
104 bool isRunning() const;
105 bool isStarted() const;
106 bool isCanceled() const;
107 bool isFinished() const;
108 bool isPaused() const;
109 bool isThrottled() const;
110 bool isResultReadyAt(int index) const;
111
112 void cancel();
113 void setPaused(bool paused);
114 void togglePaused();
115 void setThrottled(bool enable);
116
117 void waitForFinished();
118 bool waitForNextResult();
119 void waitForResult(int resultIndex);
120 void waitForResume();
121
122 QMutex *mutex() const;
123 QMutex &mutex(int) const;
124 QtPrivate::ExceptionStore &exceptionStore();
125 QtPrivate::ResultStoreBase &resultStoreBase();
126 const QtPrivate::ResultStoreBase &resultStoreBase() const;
127
128 inline bool operator==(const QFutureInterfaceBase &other) const { return d == other.d; }
129 inline bool operator!=(const QFutureInterfaceBase &other) const { return d != other.d; }
130 QFutureInterfaceBase &operator=(const QFutureInterfaceBase &other);
131
132protected:
133 bool refT() const;
134 bool derefT() const;
135public:
136
137#ifndef QFUTURE_TEST
138private:
139#endif
140 QFutureInterfaceBasePrivate *d;
141
142private:
143 friend class QFutureWatcherBase;
144 friend class QFutureWatcherBasePrivate;
145};
146
147template <typename T>
148class QFutureInterface : public QFutureInterfaceBase
149{
150public:
151 QFutureInterface(State initialState = NoState)
152 : QFutureInterfaceBase(initialState)
153 {
154 refT();
155 }
156 QFutureInterface(const QFutureInterface &other)
157 : QFutureInterfaceBase(other)
158 {
159 refT();
160 }
161 ~QFutureInterface()
162 {
163 if (!derefT())
164 resultStoreBase().template clear<T>();
165 }
166
167 static QFutureInterface canceledResult()
168 { return QFutureInterface(State(Started | Finished | Canceled)); }
169
170 QFutureInterface &operator=(const QFutureInterface &other)
171 {
172 other.refT();
173 if (!derefT())
174 resultStoreBase().template clear<T>();
175 QFutureInterfaceBase::operator=(other);
176 return *this;
177 }
178
179 inline QFuture<T> future(); // implemented in qfuture.h
180
181 inline void reportResult(const T *result, int index = -1);
182 inline void reportResult(const T &result, int index = -1);
183 inline void reportResults(const QVector<T> &results, int beginIndex = -1, int count = -1);
184 inline void reportFinished(const T *result = nullptr);
185
186 inline const T &resultReference(int index) const;
187 inline const T *resultPointer(int index) const;
188 inline QList<T> results();
189};
190
191template <typename T>
192inline void QFutureInterface<T>::reportResult(const T *result, int index)
193{
194 std::lock_guard<QMutex> locker(mutex(0));
195 if (this->queryState(Canceled) || this->queryState(Finished)) {
196 return;
197 }
198
199 QtPrivate::ResultStoreBase &store = resultStoreBase();
200
201 if (store.filterMode()) {
202 const int resultCountBefore = store.count();
203 store.addResult<T>(index, result);
204 this->reportResultsReady(resultCountBefore, store.count());
205 } else {
206 const int insertIndex = store.addResult<T>(index, result);
207 this->reportResultsReady(insertIndex, insertIndex + 1);
208 }
209}
210
211template <typename T>
212inline void QFutureInterface<T>::reportResult(const T &result, int index)
213{
214 reportResult(&result, index);
215}
216
217template <typename T>
218inline void QFutureInterface<T>::reportResults(const QVector<T> &_results, int beginIndex, int count)
219{
220 std::lock_guard<QMutex> locker(mutex(0));
221 if (this->queryState(Canceled) || this->queryState(Finished)) {
222 return;
223 }
224
225 auto &store = resultStoreBase();
226
227 if (store.filterMode()) {
228 const int resultCountBefore = store.count();
229 store.addResults(beginIndex, &_results, count);
230 this->reportResultsReady(resultCountBefore, store.count());
231 } else {
232 const int insertIndex = store.addResults(beginIndex, &_results, count);
233 this->reportResultsReady(insertIndex, insertIndex + _results.count());
234 }
235}
236
237template <typename T>
238inline void QFutureInterface<T>::reportFinished(const T *result)
239{
240 if (result)
241 reportResult(result);
242 QFutureInterfaceBase::reportFinished();
243}
244
245template <typename T>
246inline const T &QFutureInterface<T>::resultReference(int index) const
247{
248 std::lock_guard<QMutex> locker(mutex(0));
249 return resultStoreBase().resultAt(index).template value<T>();
250}
251
252template <typename T>
253inline const T *QFutureInterface<T>::resultPointer(int index) const
254{
255 std::lock_guard<QMutex> locker(mutex(0));
256 return resultStoreBase().resultAt(index).template pointer<T>();
257}
258
259template <typename T>
260inline QList<T> QFutureInterface<T>::results()
261{
262 if (this->isCanceled()) {
263 exceptionStore().throwPossibleException();
264 return QList<T>();
265 }
266 QFutureInterfaceBase::waitForResult(-1);
267
268 QList<T> res;
269 std::lock_guard<QMutex> locker(mutex(0));
270
271 QtPrivate::ResultIteratorBase it = resultStoreBase().begin();
272 while (it != resultStoreBase().end()) {
273 res.append(it.value<T>());
274 ++it;
275 }
276
277 return res;
278}
279
280template <>
281class QFutureInterface<void> : public QFutureInterfaceBase
282{
283public:
284 explicit QFutureInterface<void>(State initialState = NoState)
285 : QFutureInterfaceBase(initialState)
286 { }
287
288 static QFutureInterface<void> canceledResult()
289 { return QFutureInterface(State(Started | Finished | Canceled)); }
290
291
292 inline QFuture<void> future(); // implemented in qfuture.h
293
294 void reportResult(const void *, int) { }
295 void reportResults(const QVector<void> &, int) { }
296 void reportFinished(const void * = nullptr) { QFutureInterfaceBase::reportFinished(); }
297};
298
299QT_END_NAMESPACE
300
301#endif // QFUTUREINTERFACE_H
302