Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qpromise.qdoc
Go to the documentation of this file.
1// Copyright (C) 2020 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
3
4/*! \class QPromise
5 \inmodule QtCore
6 \threadsafe
7 \brief The QPromise class provides a way to store computation results to be accessed by QFuture.
8 \since 6.0
9
10 \ingroup thread
11
12 QPromise is a template class where the template parameter \a T specifies
13 the result type that can be stored and later accessed via QFuture.
14
15 QPromise provides a simple way to communicate progress and results of the
16 user-defined computation to QFuture in an asynchronous fashion. For the
17 communication to work, QFuture must be constructed by QPromise.
18
19 You can use QPromise based workloads as an alternative to \l {Qt Concurrent}
20 framework when fine-grained control is needed or high-level communication
21 primitive to accompany QFuture is sufficient.
22
23 The simplest case of promise and future collaboration would be a single
24 result communication:
25
26 \snippet snippet_qpromise.cpp basic
27
28 By design, QPromise is a move-only object. This behavior helps to ensure
29 that whenever the promise is destroyed, the associated future object is
30 notified and will not wait forever for the results to become available.
31 However, this is inconvenient if one wants to use the same promise to report
32 results from different threads. There is no specific way to do that at the
33 moment, but known mechanisms exist, such as the use of smart pointers or raw
34 pointers/references. QSharedPointer is a good default choice if you want to
35 copy your promise and use it in multiple places simultaneously. Raw pointers
36 or references are, in a sense, easier, and probably perform better (since
37 there is no need to do a resource management) but may lead to dangling.
38
39 Here is an example of how a promise can be used in multiple threads:
40
41 \snippet snippet_qpromise.cpp multithread_init
42 \codeline
43 \snippet snippet_qpromise.cpp multithread_main
44 \codeline
45 \snippet snippet_qpromise.cpp multithread_cleanup
46
47 \sa QFuture
48*/
49
50/*! \fn template <typename T> QPromise<T>::QPromise()
51
52 Constructs a QPromise with a default state.
53*/
54
55/*! \fn template <typename T> QPromise<T>::QPromise(QPromise<T> &&other)
56
57 Move constructs a new QPromise from \a other.
58
59 \sa operator=()
60*/
61
62/*! \fn template <typename T> QPromise<T>::QPromise(const QFutureInterface<T> &other)
63 \fn template <typename T> QPromise<T>::QPromise(QFutureInterface<T> &&other) noexcept
64
65 \internal
66 Constructs a QPromise with a passed QFutureInterface \a other.
67 Used internally for QtConcurrent::run(), when its callable takes
68 a reference to the associated promise as its first argument
69 (run with promise mode).
70
71 \sa operator=()
72*/
73
74
75/*! \fn template <typename T> QPromise<T> &QPromise<T>::operator=(QPromise<T> &&other)
76
77 Move assigns \a other to this promise and returns a reference to this
78 promise.
79*/
80
81/*! \fn template <typename T> QPromise<T>::~QPromise()
82
83 Destroys the promise.
84
85 \note The promise implicitly transitions to a canceled state on destruction
86 unless finish() is called beforehand by the user.
87*/
88
89/*! \fn template <typename T> QFuture<T> QPromise<T>::future() const
90
91 Returns a future associated with this promise.
92*/
93
94/*! \fn template <typename T> bool QPromise<T>::addResult(const T &result, int index = -1)
95 \fn template <typename T> bool QPromise<T>::addResult(T &&result, int index = -1)
96
97 Same as
98 \code
99 emplaceResultAt(index, result); // first overload
100 emplaceResultAt(index, std::move(result)); // second overload
101 \endcode
102 or, if \c{index == -1} (the default)
103 \code
104 emplaceResult(result); // first overload
105 emplaceResult(std::move(result)); // second overload
106 \endcode
107
108 \sa emplaceResultAt(), emplaceResult(), addResults()
109*/
110
111/*!
112 \fn template <typename T> template <typename...Args, std::enable_if_t<std::is_constructible_v<T, Args...>, bool> = true> bool QPromise<T>::emplaceResultAt(int index, Args&&...args)
113 \fn template <typename T> template <typename...Args, std::enable_if_t<std::is_constructible_v<T, Args...>, bool> = true> bool QPromise<T>::emplaceResult(Args&&...args)
114 \since 6.6
115
116 Adds a result constructed from \a args... to the internal result collection
117 at \a index position (emplaceResultAt()) or the end of of the collection
118 (emplaceResult()).
119
120 Returns \c true when the result was added to the collection.
121
122 Returns \c false when this promise is in canceled or finished state or when
123 the result was rejected. addResult() rejects to add a result if there's already
124 another result in the collection stored at the same index.
125
126 These functions only participate in overload resolutions if \c T is
127 constructible from \a args....
128
129 You can get a result at a specific index by calling QFuture::resultAt().
130
131 \note It is possible to specify an arbitrary index and request result at
132 that index. However, some QFuture methods operate with continuous results.
133 For instance, iterative approaches that use QFuture::resultCount() or
134 QFuture::const_iterator. In order to get all available results without
135 thinking if there are index gaps or not, use QFuture::results().
136
137 \sa addResult(), addResults()
138*/
139
140/*!
141 \fn template <typename T> bool QPromise<T>::addResults(const QList<T> &results)
142 \since 6.6
143
144 Adds \a results at the end of the internal result collection.
145
146 Returns \c true when \a results are added to the collection.
147
148 Returns \c false when this promise is in canceled or finished state.
149
150 This is more efficient than looping over addResult(), because associated
151 futures will be notified only once per addResults() call, instead of once
152 per element contained in \a results, as would be the case with individual
153 addResult() calls. But if the calculation of each element takes time, then
154 the code on the receiving end (future) cannot make progress until all
155 results are reported, so use this function only if the calculation of
156 consecutive elements is relatively fast.
157
158 \sa addResult()
159*/
160
161/*! \fn template<typename T> void QPromise<T>::setException(const QException &e)
162
163 Sets exception \a e to be the result of the computation.
164
165 \note You can set at most one exception throughout the computation
166 execution.
167
168 \note This method has no effect after QFuture::cancel() or
169 finish().
170
171 \sa isCanceled()
172*/
173
174#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0)
175/*! \fn template<typename T> void QPromise<T>::setException(std::exception_ptr e)
176
177 \overload
178*/
179#else
180/*! \fn template<typename T> void QPromise<T>::setException(const std::exception_ptr &e)
181
182 \overload
183*/
184#endif
185
186/*! \fn template<typename T> void QPromise<T>::start()
187
188 Reports that the computation is started. Calling this method is important to
189 state the beginning of the computation as QFuture methods rely on this
190 information.
191
192 \note Extra attention is required when start() is called from a
193 newly created thread. In such case, the call might naturally be delayed due
194 to the implementation details of the thread scheduling.
195
196 \sa QFuture::isStarted(), QFuture::waitForFinished(), finish()
197*/
198
199/*! \fn template<typename T> void QPromise<T>::finish()
200
201 Reports that the computation is finished. Once finished, no new results will
202 be added when calling addResult(). This method accompanies start().
203
204 \sa QFuture::isFinished(), QFuture::waitForFinished(), start()
205*/
206
207/*! \fn template<typename T> void QPromise<T>::suspendIfRequested()
208
209 Conditionally suspends current thread of execution and waits until resumed
210 or canceled by the corresponding methods of QFuture. This method does not
211 block unless the computation is requested to be suspended by
212 QFuture::suspend() or another related method. If you want to check that the
213 execution has been suspended, use QFuture::isSuspended().
214
215 \note When using the same promise in multiple threads,
216 QFuture::isSuspended() becomes \c true as soon as at least one thread with
217 the promise suspends.
218
219
220 The following code snippets show the usage of suspension mechanism:
221
222 \snippet snippet_qpromise.cpp suspend_start
223
224 QFuture::suspend() requests the associated promise to suspend:
225
226 \snippet snippet_qpromise.cpp suspend_suspend
227
228 After QFuture::isSuspended() becomes \c true, you can get intermediate
229 results:
230
231 \snippet snippet_qpromise.cpp suspend_intermediateResults
232
233 When suspended, you can resume or cancel the awaiting computation:
234
235 \snippet snippet_qpromise.cpp suspend_end
236
237
238 \sa QFuture::resume(), QFuture::cancel(), QFuture::setSuspended(),
239 QFuture::toggleSuspended()
240*/
241
242/*! \fn template<typename T> bool QPromise<T>::isCanceled() const
243
244 Returns whether the computation has been canceled with the
245 QFuture::cancel() function. The returned value \c true indicates that the
246 computation should be finished and finish() called.
247
248 \note After cancellation, results currently available may still be accessed
249 by a future, but new results will not be added when calling addResult().
250*/
251
252/*! \fn template<typename T> void QPromise<T>::setProgressRange(int minimum, int maximum)
253
254 Sets the progress range of the computation to be between \a minimum and \a
255 maximum.
256
257 If \a maximum is smaller than \a minimum, \a minimum becomes the only
258 legal value.
259
260 The progress value is reset to be \a minimum.
261
262 The progress range usage can be disabled by using setProgressRange(0, 0).
263 In this case progress value is also reset to 0.
264
265 \sa QFuture::progressMinimum(), QFuture::progressMaximum(),
266 QFuture::progressValue()
267*/
268
269/*! \fn template<typename T> void QPromise<T>::setProgressValue(int progressValue)
270
271 Sets the progress value of the computation to \a progressValue. It is
272 possible to only increment the progress value. This is a convenience method
273 for calling setProgressValueAndText(progressValue, QString()).
274
275 In case of the \a progressValue falling out of the progress range,
276 this method has no effect.
277
278 \sa QFuture::progressValue(), setProgressRange()
279*/
280
281/*! \fn template<typename T> void QPromise<T>::setProgressValueAndText(int progressValue, const QString &progressText)
282
283 Sets the progress value and the progress text of the computation to \a
284 progressValue and \a progressText respectively. It is possible to only
285 increment the progress value.
286
287 \note This function has no effect if the promise is in canceled or finished
288 state.
289
290 \sa QFuture::progressValue(), QFuture::progressText(), QFuture::cancel(),
291 finish()
292*/
293
294/*! \fn template<typename T> void QPromise<T>::swap(QPromise<T> &other) noexcept
295 \memberswap{promise}
296*/