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