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 
48 QT_REQUIRE_CONFIG(future);
49 
50 QT_BEGIN_NAMESPACE
51 
52 
53 template <typename T>
54 class QFutureWatcher;
55 template <>
56 class QFutureWatcher<void>;
57 
58 template <typename T>
59 class QFuture
60 {
61 public:
QFuture()62     QFuture()
63         : d(QFutureInterface<T>::canceledResult())
64     { }
QFuture(QFutureInterface<T> * p)65     explicit QFuture(QFutureInterface<T> *p) // internal
66         : d(*p)
67     { }
68 #if defined(Q_CLANG_QDOC)
~QFuture()69     ~QFuture() { }
QFuture(const QFuture<T> &)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 
cancel()77     void cancel() { d.cancel(); }
isCanceled()78     bool isCanceled() const { return d.isCanceled(); }
79 
setPaused(bool paused)80     void setPaused(bool paused) { d.setPaused(paused); }
isPaused()81     bool isPaused() const { return d.isPaused(); }
pause()82     void pause() { setPaused(true); }
resume()83     void resume() { setPaused(false); }
togglePaused()84     void togglePaused() { d.togglePaused(); }
85 
isStarted()86     bool isStarted() const { return d.isStarted(); }
isFinished()87     bool isFinished() const { return d.isFinished(); }
isRunning()88     bool isRunning() const { return d.isRunning(); }
89 
resultCount()90     int resultCount() const { return d.resultCount(); }
progressValue()91     int progressValue() const { return d.progressValue(); }
progressMinimum()92     int progressMinimum() const { return d.progressMinimum(); }
progressMaximum()93     int progressMaximum() const { return d.progressMaximum(); }
progressText()94     QString progressText() const { return d.progressText(); }
waitForFinished()95     void waitForFinished() { d.waitForFinished(); }
96 
97     inline T result() const;
98     inline T resultAt(int index) const;
isResultReadyAt(int resultIndex)99     bool isResultReadyAt(int resultIndex) const { return d.isResultReadyAt(resultIndex); }
100 
T()101     operator T() const { return result(); }
results()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 
const_iterator()113         inline const_iterator() {}
const_iterator(QFuture const * const _future,int _index)114         inline const_iterator(QFuture const * const _future, int _index)
115         : future(_future), index(advanceIndex(_index, 0)) { }
const_iterator(const const_iterator & o)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!=(o); }
123         inline const_iterator &operator++()
124         { index = advanceIndex(index, 1); return *this; }
125         inline const_iterator &operator--()
126         { index = advanceIndex(index, -1); return *this; }
127         inline const_iterator operator++(int)
128         {
129             const_iterator r = *this;
130             index = advanceIndex(index, 1);
131             return r;
132         }
133         inline const_iterator operator--(int)
134         {
135             const_iterator r = *this;
136             index = advanceIndex(index, -1);
137             return r;
138         }
139         inline const_iterator operator+(int j) const
140         { return const_iterator(future, advanceIndex(index, j)); }
141         inline const_iterator operator-(int j) const
142         { return const_iterator(future, advanceIndex(index, -j)); }
143         inline const_iterator &operator+=(int j)
144         { index = advanceIndex(index, j); return *this; }
145         inline const_iterator &operator-=(int j)
146         { index = advanceIndex(index, -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         */
advanceIndex(int idx,int n)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 
begin()193     const_iterator begin() const { return  const_iterator(this, 0); }
constBegin()194     const_iterator constBegin() const { return  const_iterator(this, 0); }
end()195     const_iterator end() const { return const_iterator(this, -1); }
constEnd()196     const_iterator constEnd() const { return const_iterator(this, -1); }
197 
198 private:
199     friend class QFutureWatcher<T>;
200 
201 public: // Warning: the d pointer is not documented and is considered private.
202     mutable QFutureInterface<T> d;
203 };
204 
205 template <typename T>
result()206 inline T QFuture<T>::result() const
207 {
208     d.waitForResult(0);
209     return d.resultReference(0);
210 }
211 
212 template <typename T>
resultAt(int index)213 inline T QFuture<T>::resultAt(int index) const
214 {
215     d.waitForResult(index);
216     return d.resultReference(index);
217 }
218 
219 template <typename T>
future()220 inline QFuture<T> QFutureInterface<T>::future()
221 {
222     return QFuture<T>(this);
223 }
224 
Q_DECLARE_SEQUENTIAL_ITERATOR(Future)225 Q_DECLARE_SEQUENTIAL_ITERATOR(Future)
226 
227 template <>
228 class QFuture<void>
229 {
230 public:
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 
275 private:
276     friend class QFutureWatcher<void>;
277 
278 #ifdef QFUTURE_TEST
279 public:
280 #endif
281     mutable QFutureInterfaceBase d;
282 };
283 
future()284 inline QFuture<void> QFutureInterface<void>::future()
285 {
286     return QFuture<void>(this);
287 }
288 
289 template <typename T>
qToVoidFuture(const QFuture<T> & future)290 QFuture<void> qToVoidFuture(const QFuture<T> &future)
291 {
292     return QFuture<void>(future.d);
293 }
294 
295 QT_END_NAMESPACE
296 
297 #endif // QFUTURE_H
298