QtBase  v6.3.1
src_corelib_thread_qfuture.cpp
Go to the documentation of this file.
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 documentation of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:BSD$
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 ** BSD License Usage
18 ** Alternatively, you may use this file under the terms of the BSD license
19 ** as follows:
20 **
21 ** "Redistribution and use in source and binary forms, with or without
22 ** modification, are permitted provided that the following conditions are
23 ** met:
24 ** * Redistributions of source code must retain the above copyright
25 ** notice, this list of conditions and the following disclaimer.
26 ** * Redistributions in binary form must reproduce the above copyright
27 ** notice, this list of conditions and the following disclaimer in
28 ** the documentation and/or other materials provided with the
29 ** distribution.
30 ** * Neither the name of The Qt Company Ltd nor the names of its
31 ** contributors may be used to endorse or promote products derived
32 ** from this software without specific prior written permission.
33 **
34 **
35 ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
36 ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
37 ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
38 ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
39 ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
40 ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
41 ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
42 ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
43 ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
44 ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
45 ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
46 **
47 ** $QT_END_LICENSE$
48 **
49 ****************************************************************************/
50 
53 
55 for (i = future.constBegin(); i != future.constEnd(); ++i)
56  cout << *i << Qt::endl;
58 
59 
62 ...
63 QFutureIterator<QString> i(future);
64 while (i.hasNext())
65  QString s = i.next();
67 
68 
70 QFutureIterator<QString> i(future);
71 i.toBack();
72 while (i.hasPrevious())
73  QString s = i.previous();
75 
77 using NetworkReply = std::variant<QByteArray, QNetworkReply::NetworkError>;
78 
80 using IOResult = std::variant<QString, IOError>;
82 
85  ...
87 }).then([](NetworkReply reply) {
88  if (auto error = std::get_if<QNetworkReply::NetworkError>(&reply))
90 
91  auto data = std::get_if<QByteArray>(&reply);
92  // try to write *data and return IOError::FailedToWrite on failure
93  ...
94 });
95 
96 auto result = future.result();
97 if (auto filePath = std::get_if<QString>(&result)) {
98  // do something with *filePath
99 else
100  // process the error
102 
104 QFuture<int> future = ...;
105  future.then([](QFuture<int> f) {
106  try {
107  ...
108  auto result = f.result();
109  ...
110  } catch (QException &e) {
111  // handle the exception
112  }
113  }).then(...);
115 
117 QFuture<int> future = ...;
118 auto continuation = future.then([](int res1){ ... }).then([](int res2){ ... })...
119 ...
120 // future throws an exception
121 try {
122  auto result = continuation.result();
123 } catch (QException &e) {
124  // handle the exception
125 }
127 
129 QFuture<int> future = ...;
130 auto resultFuture = future.then([](int res) {
131  ...
132  throw Error();
133  ...
134 }).onFailed([](const Error &e) {
135  // Handle exceptions of type Error
136  ...
137  return -1;
138 }).onFailed([] {
139  // Handle all other types of errors
140  ...
141  return -1;
142 });
143 
144 auto result = resultFuture.result(); // result is -1
146 
148 QFuture<int> future = ...;
149 future.then([](int res) {
150  ...
151  throw std::runtime_error("message");
152  ...
153 }).onFailed([](const std::exception &e) {
154  // This handler will be invoked
155 }).onFailed([](const std::runtime_error &e) {
156  // This handler won't be invoked, because of the handler above.
157 });
159 
161 QFuture<int> future = ...;
162 auto resultFuture = future.then([](int res) {
163  ...
164  throw Error("message");
165  ...
166 }).onFailed([](const std::exception &e) {
167  // Won't be invoked
168 }).onFailed([](const QException &e) {
169  // Won't be invoked
170 });
171 
172 try {
173  auto result = resultFuture.result();
174 } catch(...) {
175  // Handle the exception
176 }
178 
180 class Object : public QObject
181 {
182  Q_OBJECT
183  ...
184 signals:
185  void noArgSignal();
186  void singleArgSignal(int value);
187  void multipleArgs(int value1, double value2, const QString &value3);
188 };
190 
192 Object object;
193 QFuture<void> voidFuture = QtFuture::connect(&object, &Object::noArgSignal);
194 QFuture<int> intFuture = QtFuture::connect(&object, &Object::singleArgSignal);
195 
196 using Args = std::tuple<int, double, QString>;
197 QFuture<Args> tupleFuture = QtFuture::connect(&object, &Object::multipleArgs)
199 
201 QtFuture::connect(&object, &Object::singleArgSignal).then([](int value) {
202  // do something with the value
203 });
205 
207 QtFuture::connect(&object, &Object::singleArgSignal).then(QtFuture::Launch::Async, [](int value) {
208  // this will run in a new thread
209 });
211 
213 QtFuture::connect(&object, &Object::singleArgSignal).then([](int value) {
214  ...
215  throw std::exception();
216  ...
217 }).onFailed([](const std::exception &e) {
218  // handle the exception
219 }).onFailed([] {
220  // handle other exceptions
221 });
223 
225 QFuture<int> testFuture = ...;
226 auto resultFuture = testFuture.then([](int res) {
227  // Block 1
228 }).onCanceled([] {
229  // Block 2
230 }).onFailed([] {
231  // Block 3
232 }).then([] {
233  // Block 4
234 }).onFailed([] {
235  // Block 5
236 }).onCanceled([] {
237  // Block 6
238 });
240 
242 QFuture<int> testFuture = ...;
243 auto resultFuture = testFuture.then([](int res) {
244  // Block 1
245 }).onFailed([] {
246  // Block 3
247 }).then([] {
248  // Block 4
249 }).onFailed([] {
250  // Block 5
251 }).onCanceled([] {
252  // Block 6
253 });
255 
257 // somewhere in the main thread
258 auto future = QtConcurrent::run([] {
259  // This will run in a separate thread
260  ...
261 }).then(this, [] {
262  // Update UI elements
263 });
265 
267 auto future = QtConcurrent::run([] {
268  ...
269 }).then(this, [] {
270  // Update UI elements
271 }).then([] {
272  // This will also run in the main thread
273 });
275 
277 // somewhere in the main thread
278 auto future = QtConcurrent::run([] {
279  // This will run in a separate thread
280  ...
281  throw std::exception();
282 }).onFailed(this, [] {
283  // Update UI elements
284 });
286 
288 QObject *context = ...;
289 auto future = cachedResultsReady ? QtFuture::makeReadyFuture(results)
290  : QtConcurrent::run([] { /* compute results */});
291 auto continuation = future.then(context, [] (Results results) {
292  // Runs in the context's thread
293 }).then([] {
294  // May or may not run in the context's thread
295 });
297 
299 QFuture<int> testFuture = ...;
300 auto resultFuture = testFuture.then([](int res) {
301  // Block 1
302  ...
303  return 1;
304 }).then([](int res) {
305  // Block 2
306  ...
307  return 2;
308 }).onCanceled([] {
309  // Block 3
310  ...
311  return -1;
312 });
314 
316 QList<QFuture<int>> inputFutures {...};
317 
318 // whenAll has type QFuture<QList<QFuture<int>>>
319 auto whenAll = QtFuture::whenAll(inputFutures.begin(), inputFutures.end());
320 
321 // whenAllVector has type QFuture<std::vector<QFuture<int>>>
322 auto whenAllVector =
323  QtFuture::whenAll<std::vector<QFuture<int>>>(inputFutures.begin(), inputFutures.end());
325 
327 QList<QFuture<int>> inputFutures {...};
328 
329 QtFuture::whenAll(inputFutures.begin(), inputFutures.end())
330  .then([](const QList<QFuture<int>> &results) {
331  for (auto future : results) {
332  if (future.isCanceled())
333  // handle the cancellation (possibly due to an exception)
334  else
335  // do something with the result
336  }
337  });
339 
341 
342 QFuture<int> intFuture = ...;
343 QFuture<QString> stringFuture = ...;
344 QFuture<void> voidFuture = ...;
345 
346 using FuturesVariant = std::variant<QFuture<int>, QFuture<QString>, QFuture<void>>;
347 
348 // whenAll has type QFuture<QList<FuturesVariant>>
349 auto whenAll = QtFuture::whenAll(intFuture, stringFuture, voidFuture);
350 
351 // whenAllVector has type QFuture<std::vector<FuturesVariant>>
352 auto whenAllVector =
353  QtFuture::whenAll<std::vector<FuturesVariant>>(intFuture, stringFuture, voidFuture);
354 
356 
358 QFuture<int> intFuture = ...;
359 QFuture<QString> stringFuture = ...;
360 QFuture<void> voidFuture = ...;
361 
362 using FuturesVariant = std::variant<QFuture<int>, QFuture<QString>, QFuture<void>>;
363 
364 QtFuture::whenAll(intFuture, stringFuture, voidFuture)
365  .then([](const QList<FuturesVariant> &results) {
366  ...
367  for (auto result : results)
368  {
369  // assuming handleResult() is overloaded based on the QFuture type
370  std::visit([](auto &&future) { handleResult(future); }, result);
371  }
372  ...
373  });
375 
377 QList<QFuture<int>> inputFutures = ...;
378 
379 QtFuture::whenAny(inputFutures.begin(), inputFutures.end())
380  .then([](const QtFuture::WhenAnyResult<int> &result) {
381  qsizetype index = result.index;
382  QFuture<int> future = result.future;
383  // ...
384  });
386 
388 QFuture<int> intFuture = ...;
389 QFuture<QString> stringFuture = ...;
390 QFuture<void> voidFuture = ...;
391 
392 using FuturesVariant = std::variant<QFuture<int>, QFuture<QString>, QFuture<void>>;
393 
394 QtFuture::whenAny(intFuture, stringFuture, voidFuture).then([](const FuturesVariant &result) {
395  ...
396  // assuming handleResult() is overloaded based on the QFuture type
397  std::visit([](auto &&future) { handleResult(future); }, result);
398  ...
399 });
FT_Error error
Definition: cffdrivr.c:657
Definition: main.cpp:55
The QException class provides a base class for exceptions that can be transferred across threads.
Definition: qexception.h:58
QFuture< ResultType< Function > > then(Function &&function)
Definition: qlist.h:108
iterator end()
Definition: qlist.h:624
iterator begin()
Definition: qlist.h:623
The QObject class is the base class of all Qt objects.
Definition: qobject.h:125
The QString class provides a Unicode character string.
Definition: qstring.h:388
double e
std::ostream & cout()
@ Error
Definition: qprint_p.h:94
auto run(QThreadPool *pool, Function &&f, Args &&...args)
QFuture< WhenAnyResult< typename QtPrivate::Future< ValueType >::type > > whenAny(InputIt first, InputIt last)
Definition: qfuture.h:510
QFuture< OutputSequence > whenAll(InputIt first, InputIt last)
Definition: qfuture.h:472
QTextStream & endl(QTextStream &stream)
EGLOutputLayerEXT EGLint EGLAttrib value
ptrdiff_t qsizetype
Definition: qglobal.h:308
GLuint index
[2]
GLuint object
[3]
GLfloat GLfloat f
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLuint res
Definition: qopenglext.h:8867
GLuint64EXT * result
[6]
Definition: qopenglext.h:10932
GLdouble s
[6]
Definition: qopenglext.h:235
#define Q_OBJECT
Definition: qtmetamacros.h:158
QList< int > results
QUrl url("http://www.example.com/List of holidays.xml")
[0]
std::variant< QString, IOError > IOResult
std::variant< QByteArray, QNetworkReply::NetworkError > NetworkReply
[2]
QFuture< QString > future
[0]
QFuture< QString >::const_iterator i
@ FailedToWrite
@ FailedToRead
QNetworkReply * reply
Definition: main.cpp:58