1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
|
// Copyright (C) 2020 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
// Note: this file is published under a license that is different from a default
// test sources license. This is intentional to comply with default
// snippet license.
#include <QCoreApplication>
#include <QTest>
#include <qfuture.h>
#include <qfuturewatcher.h>
#include <qpromise.h>
#include <qscopedpointer.h>
#include <qsharedpointer.h>
class snippet_QPromise
{
public:
static void basicExample();
static void multithreadExample();
static void suspendExample();
};
void snippet_QPromise::basicExample()
{
#if QT_CONFIG(cxx11_future)
//! [basic]
QPromise<int> promise;
QFuture<int> future = promise.future();
QScopedPointer<QThread> thread(QThread::create([] (QPromise<int> promise) {
promise.start(); // notifies QFuture that the computation is started
promise.addResult(42);
promise.finish(); // notifies QFuture that the computation is finished
}, std::move(promise)));
thread->start();
future.waitForFinished(); // blocks until QPromise::finish is called
future.result(); // returns 42
//! [basic]
QCOMPARE(future.result(), 42);
thread->wait();
#endif
}
void snippet_QPromise::multithreadExample()
{
#if QT_CONFIG(cxx11_future)
//! [multithread_init]
QSharedPointer<QPromise<int>> sharedPromise(new QPromise<int>());
QFuture<int> future = sharedPromise->future();
// ...
sharedPromise->start();
//! [multithread_init]
//! [multithread_main]
// here, QPromise is shared between threads via a smart pointer
QScopedPointer<QThread> threads[] = {
QScopedPointer<QThread>(QThread::create([] (auto sharedPromise) {
sharedPromise->addResult(0, 0); // adds value 0 by index 0
}, sharedPromise)),
QScopedPointer<QThread>(QThread::create([] (auto sharedPromise) {
sharedPromise->addResult(-1, 1); // adds value -1 by index 1
}, sharedPromise)),
QScopedPointer<QThread>(QThread::create([] (auto sharedPromise) {
sharedPromise->addResult(-2, 2); // adds value -2 by index 2
}, sharedPromise)),
// ...
};
// start all threads
for (auto& t : threads)
t->start();
// ...
future.resultAt(0); // waits until result at index 0 becomes available. returns value 0
future.resultAt(1); // waits until result at index 1 becomes available. returns value -1
future.resultAt(2); // waits until result at index 2 becomes available. returns value -2
//! [multithread_main]
QCOMPARE(future.resultAt(0), 0);
QCOMPARE(future.resultAt(1), -1);
QCOMPARE(future.resultAt(2), -2);
for (auto& t : threads)
t->wait();
//! [multithread_cleanup]
sharedPromise->finish();
//! [multithread_cleanup]
#endif
}
void snippet_QPromise::suspendExample()
{
#if QT_CONFIG(cxx11_future)
//! [suspend_start]
// Create promise and future
QPromise<int> promise;
QFuture<int> future = promise.future();
promise.start();
// Start a computation thread that supports suspension and cancellation
QScopedPointer<QThread> thread(QThread::create([] (QPromise<int> promise) {
for (int i = 0; i < 100; ++i) {
promise.addResult(i);
promise.suspendIfRequested(); // support suspension
if (promise.isCanceled()) // support cancellation
break;
}
promise.finish();
}, std::move(promise)));
thread->start();
//! [suspend_start]
//! [suspend_suspend]
future.suspend();
//! [suspend_suspend]
// wait in calling thread until future.isSuspended() becomes true or do
// something meanwhile
while (!future.isSuspended()) {
QThread::msleep(50);
}
//! [suspend_intermediateResults]
future.resultCount(); // returns some number between 0 and 100
for (int i = 0; i < future.resultCount(); ++i) {
// process results available before suspension
}
//! [suspend_intermediateResults]
// at least one result is available due to the logic inside a thread
QVERIFY(future.resultCount() > 0);
QVERIFY(future.resultCount() <= 100);
for (int i = 0; i < future.resultCount(); ++i) {
QCOMPARE(future.resultAt(i), i);
}
//! [suspend_end]
future.resume(); // resumes computation, this call will unblock the promise
// alternatively, call future.cancel() to stop the computation
future.waitForFinished();
future.results(); // returns all computation results - array of values from 0 to 99
//! [suspend_end]
thread->wait();
QCOMPARE(future.resultCount(), 100);
QList<int> expected(100);
std::iota(expected.begin(), expected.end(), 0);
QCOMPARE(future.results(), expected);
#endif
}
|