1/****************************************************************************
2**
3** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
4** Contact: http://www.qt-project.org/legal
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 Digia. For licensing terms and
14** conditions see http://qt.digia.com/licensing. For further information
15** use the contact form at http://qt.digia.com/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 2.1 as published by the Free Software
20** Foundation and appearing in the file LICENSE.LGPL included in the
21** packaging of this file. Please review the following information to
22** ensure the GNU Lesser General Public License version 2.1 requirements
23** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24**
25** In addition, as a special exception, Digia gives you certain additional
26** rights. These rights are described in the Digia Qt LGPL Exception
27** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28**
29** GNU General Public License Usage
30** Alternatively, this file may be used under the terms of the GNU
31** General Public License version 3.0 as published by the Free Software
32** Foundation and appearing in the file LICENSE.GPL included in the
33** packaging of this file. Please review the following information to
34** ensure the GNU General Public License version 3.0 requirements will be
35** met: http://www.gnu.org/copyleft/gpl.html.
36**
37**
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#ifndef QFUTUREINTERFACE_H
43#define QFUTUREINTERFACE_H
44
45#include <QtCore/qglobal.h>
46#include <QtCore/qrunnable.h>
47
48#ifndef QT_NO_QFUTURE
49
50#include <QtCore/qmutex.h>
51#include <QtCore/qtconcurrentexception.h>
52#include <QtCore/qtconcurrentresultstore.h>
53
54QT_BEGIN_HEADER
55QT_BEGIN_NAMESPACE
56
57QT_MODULE(Core)
58
59template <typename T> class QFuture;
60class QFutureInterfaceBasePrivate;
61class QFutureWatcherBase;
62class QFutureWatcherBasePrivate;
63
64class Q_CORE_EXPORT QFutureInterfaceBase
65{
66public:
67 enum State {
68 NoState = 0x00,
69 Running = 0x01,
70 Started = 0x02,
71 Finished = 0x04,
72 Canceled = 0x08,
73 Paused = 0x10,
74 Throttled = 0x20
75 };
76
77 QFutureInterfaceBase(State initialState = NoState);
78 QFutureInterfaceBase(const QFutureInterfaceBase &other);
79 virtual ~QFutureInterfaceBase();
80
81 // reporting functions available to the engine author:
82 void reportStarted();
83 void reportFinished();
84 void reportCanceled();
85#ifndef QT_NO_EXCEPTIONS
86 void reportException(const QtConcurrent::Exception &e);
87#endif
88 void reportResultsReady(int beginIndex, int endIndex);
89
90 void setRunnable(QRunnable *runnable);
91 void setFilterMode(bool enable);
92 void setProgressRange(int minimum, int maximum);
93 int progressMinimum() const;
94 int progressMaximum() const;
95 bool isProgressUpdateNeeded() const;
96 void setProgressValue(int progressValue);
97 int progressValue() const;
98 void setProgressValueAndText(int progressValue, const QString &progressText);
99 QString progressText() const;
100
101 void setExpectedResultCount(int resultCount);
102 int expectedResultCount();
103 int resultCount() const;
104
105 bool queryState(State state) const;
106 bool isRunning() const;
107 bool isStarted() const;
108 bool isCanceled() const;
109 bool isFinished() const;
110 bool isPaused() const;
111 bool isThrottled() const;
112 bool isResultReadyAt(int index) const;
113
114 void cancel();
115 void setPaused(bool paused);
116 void togglePaused();
117 void setThrottled(bool enable);
118
119 void waitForFinished();
120 bool waitForNextResult();
121 void waitForResult(int resultIndex);
122 void waitForResume();
123
124 QMutex *mutex() const;
125 QtConcurrent::internal::ExceptionStore &exceptionStore();
126 QtConcurrent::ResultStoreBase &resultStoreBase();
127 const QtConcurrent::ResultStoreBase &resultStoreBase() const;
128
129 inline bool operator==(const QFutureInterfaceBase &other) const { return d == other.d; }
130 inline bool operator!=(const QFutureInterfaceBase &other) const { return d != other.d; }
131 QFutureInterfaceBase &operator=(const QFutureInterfaceBase &other);
132
133protected:
134 bool referenceCountIsOne() 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 QFutureInterface(const QFutureInterface &other)
155 : QFutureInterfaceBase(other)
156 { }
157 ~QFutureInterface()
158 {
159 if (referenceCountIsOne())
160 resultStore().clear();
161 }
162
163 static QFutureInterface canceledResult()
164 { return QFutureInterface(State(Started | Finished | Canceled)); }
165
166 QFutureInterface &operator=(const QFutureInterface &other)
167 {
168 if (referenceCountIsOne())
169 resultStore().clear();
170 QFutureInterfaceBase::operator=(other);
171 return *this;
172 }
173
174 inline QFuture<T> future(); // implemented in qfuture.h
175
176 inline void reportResult(const T *result, int index = -1);
177 inline void reportResult(const T &result, int index = -1);
178 inline void reportResults(const QVector<T> &results, int beginIndex = -1, int count = -1);
179 inline void reportFinished(const T *result = 0);
180
181 inline const T &resultReference(int index) const;
182 inline const T *resultPointer(int index) const;
183 inline QList<T> results();
184private:
185 QtConcurrent::ResultStore<T> &resultStore()
186 { return static_cast<QtConcurrent::ResultStore<T> &>(resultStoreBase()); }
187 const QtConcurrent::ResultStore<T> &resultStore() const
188 { return static_cast<const QtConcurrent::ResultStore<T> &>(resultStoreBase()); }
189};
190
191template <typename T>
192inline void QFutureInterface<T>::reportResult(const T *result, int index)
193{
194 QMutexLocker locker(mutex());
195 if (this->queryState(Canceled) || this->queryState(Finished)) {
196 return;
197 }
198
199 QtConcurrent::ResultStore<T> &store = resultStore();
200
201
202 if (store.filterMode()) {
203 const int resultCountBefore = store.count();
204 store.addResult(index, result);
205 this->reportResultsReady(resultCountBefore, resultCountBefore + store.count());
206 } else {
207 const int insertIndex = store.addResult(index, result);
208 this->reportResultsReady(insertIndex, insertIndex + 1);
209 }
210}
211
212template <typename T>
213inline void QFutureInterface<T>::reportResult(const T &result, int index)
214{
215 reportResult(&result, index);
216}
217
218template <typename T>
219inline void QFutureInterface<T>::reportResults(const QVector<T> &_results, int beginIndex, int count)
220{
221 QMutexLocker locker(mutex());
222 if (this->queryState(Canceled) || this->queryState(Finished)) {
223 return;
224 }
225
226 QtConcurrent::ResultStore<T> &store = resultStore();
227
228 if (store.filterMode()) {
229 const int resultCountBefore = store.count();
230 store.addResults(beginIndex, &_results, count);
231 this->reportResultsReady(resultCountBefore, store.count());
232 } else {
233 const int insertIndex = store.addResults(beginIndex, &_results, count);
234 this->reportResultsReady(insertIndex, insertIndex + _results.count());
235 }
236}
237
238template <typename T>
239inline void QFutureInterface<T>::reportFinished(const T *result)
240{
241 if (result)
242 reportResult(result);
243 QFutureInterfaceBase::reportFinished();
244}
245
246template <typename T>
247inline const T &QFutureInterface<T>::resultReference(int index) const
248{
249 QMutexLocker lock(mutex());
250 return resultStore().resultAt(index).value();
251}
252
253template <typename T>
254inline const T *QFutureInterface<T>::resultPointer(int index) const
255{
256 QMutexLocker lock(mutex());
257 return resultStore().resultAt(index).pointer();
258}
259
260template <typename T>
261inline QList<T> QFutureInterface<T>::results()
262{
263 if (this->isCanceled()) {
264 exceptionStore().throwPossibleException();
265 return QList<T>();
266 }
267 QFutureInterfaceBase::waitForResult(-1);
268
269 QList<T> res;
270 QMutexLocker lock(mutex());
271
272 QtConcurrent::ResultIterator<T> it = resultStore().begin();
273 while (it != resultStore().end()) {
274 res.append(it.value());
275 ++it;
276 }
277
278 return res;
279}
280
281template <>
282class QFutureInterface<void> : public QFutureInterfaceBase
283{
284public:
285 QFutureInterface<void>(State initialState = NoState)
286 : QFutureInterfaceBase(initialState)
287 { }
288 QFutureInterface<void>(const QFutureInterface<void> &other)
289 : QFutureInterfaceBase(other)
290 { }
291
292 static QFutureInterface<void> canceledResult()
293 { return QFutureInterface(State(Started | Finished | Canceled)); }
294
295 QFutureInterface<void> &operator=(const QFutureInterface<void> &other)
296 {
297 QFutureInterfaceBase::operator=(other);
298 return *this;
299 }
300
301 inline QFuture<void> future(); // implemented in qfuture.h
302
303 void reportResult(const void *, int) { }
304 void reportResults(const QVector<void> &, int) { }
305 void reportFinished(void * = 0) { QFutureInterfaceBase::reportFinished(); }
306};
307
308QT_END_NAMESPACE
309QT_END_HEADER
310
311#endif // QT_NO_CONCURRENT
312
313#endif // QFUTUREINTERFACE_H
314