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 QFUTURE_H
41#define QFUTURE_H
42
43#include <QtCore/qglobal.h>
44
45#include <QtCore/qfutureinterface.h>
46#include <QtCore/qstring.h>
47
48QT_REQUIRE_CONFIG(future);
49
50QT_BEGIN_NAMESPACE
51
52
53template <typename T>
54class QFutureWatcher;
55template <>
56class QFutureWatcher<void>;
57
58template <typename T>
59class QFuture
60{
61public:
62 QFuture()
63 : d(QFutureInterface<T>::canceledResult())
64 { }
65 explicit QFuture(QFutureInterface<T> *p) // internal
66 : d(*p)
67 { }
68#if defined(Q_CLANG_QDOC)
69 ~QFuture() { }
70 QFuture(const QFuture<T> &) { }
71 QFuture<T> & operator=(const QFuture<T> &) { }
72#endif
73
74 bool operator==(const QFuture &other) const { return (d == other.d); }
75 bool operator!=(const QFuture &other) const { return (d != other.d); }
76
77 void cancel() { d.cancel(); }
78 bool isCanceled() const { return d.isCanceled(); }
79
80 void setPaused(bool paused) { d.setPaused(paused); }
81 bool isPaused() const { return d.isPaused(); }
82 void pause() { setPaused(true); }
83 void resume() { setPaused(false); }
84 void togglePaused() { d.togglePaused(); }
85
86 bool isStarted() const { return d.isStarted(); }
87 bool isFinished() const { return d.isFinished(); }
88 bool isRunning() const { return d.isRunning(); }
89
90 int resultCount() const { return d.resultCount(); }
91 int progressValue() const { return d.progressValue(); }
92 int progressMinimum() const { return d.progressMinimum(); }
93 int progressMaximum() const { return d.progressMaximum(); }
94 QString progressText() const { return d.progressText(); }
95 void waitForFinished() { d.waitForFinished(); }
96
97 inline T result() const;
98 inline T resultAt(int index) const;
99 bool isResultReadyAt(int resultIndex) const { return d.isResultReadyAt(resultIndex); }
100
101 operator T() const { return result(); }
102 QList<T> results() const { return d.results(); }
103
104 class const_iterator
105 {
106 public:
107 typedef std::bidirectional_iterator_tag iterator_category;
108 typedef qptrdiff difference_type;
109 typedef T value_type;
110 typedef const T *pointer;
111 typedef const T &reference;
112
113 inline const_iterator() {}
114 inline const_iterator(QFuture const * const _future, int _index)
115 : future(_future), index(advanceIndex(idx: _index, n: 0)) { }
116 inline const_iterator(const const_iterator &o) : future(o.future), index(o.index) {}
117 inline const_iterator &operator=(const const_iterator &o)
118 { future = o.future; index = o.index; return *this; }
119 inline const T &operator*() const { return future->d.resultReference(index); }
120 inline const T *operator->() const { return future->d.resultPointer(index); }
121 inline bool operator!=(const const_iterator &other) const { return index != other.index; }
122 inline bool operator==(const const_iterator &o) const { return !operator!=(other: o); }
123 inline const_iterator &operator++()
124 { index = advanceIndex(idx: index, n: 1); return *this; }
125 inline const_iterator &operator--()
126 { index = advanceIndex(idx: index, n: -1); return *this; }
127 inline const_iterator operator++(int)
128 {
129 const_iterator r = *this;
130 index = advanceIndex(idx: index, n: 1);
131 return r;
132 }
133 inline const_iterator operator--(int)
134 {
135 const_iterator r = *this;
136 index = advanceIndex(idx: index, n: -1);
137 return r;
138 }
139 inline const_iterator operator+(int j) const
140 { return const_iterator(future, advanceIndex(idx: index, n: j)); }
141 inline const_iterator operator-(int j) const
142 { return const_iterator(future, advanceIndex(idx: index, n: -j)); }
143 inline const_iterator &operator+=(int j)
144 { index = advanceIndex(idx: index, n: j); return *this; }
145 inline const_iterator &operator-=(int j)
146 { index = advanceIndex(idx: index, n: -j); return *this; }
147 friend inline const_iterator operator+(int j, const_iterator k)
148 { return const_iterator(k.future, k.advanceIndex(k.index, j)); }
149
150 private:
151 /*! \internal
152
153 Advances the iterator index \a idx \a n steps, waits for the
154 result at the target index, and returns the target index.
155
156 The index may be -1, indicating the end iterator, either
157 as the argument or as the return value. The end iterator
158 may be decremented.
159
160 The caller is responsible for not advancing the iterator
161 before begin() or past end(), with the exception that
162 attempting to advance a non-end iterator past end() for
163 a running future is allowed and will return the end iterator.
164
165 Note that n == 0 is valid and will wait for the result
166 at the given index.
167 */
168 int advanceIndex(int idx, int n) const
169 {
170 // The end iterator can be decremented, leave as-is for other cases
171 if (idx == -1 && n >= 0)
172 return idx;
173
174 // Special case for decrementing the end iterator: wait for
175 // finished to get the total result count.
176 if (idx == -1 && future->isRunning())
177 future->d.waitForFinished();
178
179 // Wait for result at target index
180 const int targetIndex = (idx == -1) ? future->resultCount() + n : idx + n;
181 future->d.waitForResult(targetIndex);
182
183 // After waiting there is either a result or the end was reached
184 return (targetIndex < future->resultCount()) ? targetIndex : -1;
185 }
186
187 QFuture const * future;
188 int index;
189 };
190 friend class const_iterator;
191 typedef const_iterator ConstIterator;
192
193 const_iterator begin() const { return const_iterator(this, 0); }
194 const_iterator constBegin() const { return const_iterator(this, 0); }
195 const_iterator end() const { return const_iterator(this, -1); }
196 const_iterator constEnd() const { return const_iterator(this, -1); }
197
198private:
199 friend class QFutureWatcher<T>;
200
201public: // Warning: the d pointer is not documented and is considered private.
202 mutable QFutureInterface<T> d;
203};
204
205template <typename T>
206inline T QFuture<T>::result() const
207{
208 d.waitForResult(0);
209 return d.resultReference(0);
210}
211
212template <typename T>
213inline T QFuture<T>::resultAt(int index) const
214{
215 d.waitForResult(index);
216 return d.resultReference(index);
217}
218
219template <typename T>
220inline QFuture<T> QFutureInterface<T>::future()
221{
222 return QFuture<T>(this);
223}
224
225Q_DECLARE_SEQUENTIAL_ITERATOR(Future)
226
227template <>
228class QFuture<void>
229{
230public:
231 QFuture()
232 : d(QFutureInterface<void>::canceledResult())
233 { }
234 explicit QFuture(QFutureInterfaceBase *p) // internal
235 : d(*p)
236 { }
237
238 bool operator==(const QFuture &other) const { return (d == other.d); }
239 bool operator!=(const QFuture &other) const { return (d != other.d); }
240
241#if !defined(Q_CC_XLC)
242 template <typename T>
243 QFuture(const QFuture<T> &other)
244 : d(other.d)
245 { }
246
247 template <typename T>
248 QFuture<void> &operator=(const QFuture<T> &other)
249 {
250 d = other.d;
251 return *this;
252 }
253#endif
254
255 void cancel() { d.cancel(); }
256 bool isCanceled() const { return d.isCanceled(); }
257
258 void setPaused(bool paused) { d.setPaused(paused); }
259 bool isPaused() const { return d.isPaused(); }
260 void pause() { setPaused(true); }
261 void resume() { setPaused(false); }
262 void togglePaused() { d.togglePaused(); }
263
264 bool isStarted() const { return d.isStarted(); }
265 bool isFinished() const { return d.isFinished(); }
266 bool isRunning() const { return d.isRunning(); }
267
268 int resultCount() const { return d.resultCount(); }
269 int progressValue() const { return d.progressValue(); }
270 int progressMinimum() const { return d.progressMinimum(); }
271 int progressMaximum() const { return d.progressMaximum(); }
272 QString progressText() const { return d.progressText(); }
273 void waitForFinished() { d.waitForFinished(); }
274
275private:
276 friend class QFutureWatcher<void>;
277
278#ifdef QFUTURE_TEST
279public:
280#endif
281 mutable QFutureInterfaceBase d;
282};
283
284inline QFuture<void> QFutureInterface<void>::future()
285{
286 return QFuture<void>(this);
287}
288
289template <typename T>
290QFuture<void> qToVoidFuture(const QFuture<T> &future)
291{
292 return QFuture<void>(future.d);
293}
294
295QT_END_NAMESPACE
296
297#endif // QFUTURE_H
298

source code of qtbase/src/corelib/thread/qfuture.h