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