1// Copyright (C) 2020 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
7 \brief The QPromise class provides a way to store computation results to be accessed by QFuture.
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.
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.
20 The simplest case of promise and future collaboration would be a single
23 \snippet snippet_qpromise.cpp basic
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.
36 Here is an example of how a promise can be used in multiple threads:
38 \snippet snippet_qpromise.cpp multithread_init
40 \snippet snippet_qpromise.cpp multithread_main
42 \snippet snippet_qpromise.cpp multithread_cleanup
47/*! \fn template <typename T> QPromise<T>::QPromise()
49 Constructs a QPromise with a default state.
52/*! \fn template <typename T> QPromise<T>::QPromise(QPromise<T> &&other)
54 Move constructs a new QPromise from \a other.
59/*! \fn template <typename T> QPromise<T>::QPromise(const QFutureInterface<T> &other)
60 \fn template <typename T> QPromise<T>::QPromise(QFutureInterface<T> &&other) noexcept
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).
72/*! \fn template <typename T> QPromise<T> &QPromise<T>::operator=(QPromise<T> &&other)
74 Move assigns \a other to this promise and returns a reference to this
78/*! \fn template <typename T> QPromise<T>::~QPromise()
82 \note The promise implicitly transitions to a canceled state on destruction
83 unless finish() is called beforehand by the user.
86/*! \fn template <typename T> QFuture<T> QPromise<T>::future() const
88 Returns a future associated with this promise.
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)
96 emplaceResultAt(index, result); // first overload
97 emplaceResultAt(index, std::move(result)); // second overload
99 or, if \c{index == -1} (the default)
101 emplaceResult(result); // first overload
102 emplaceResult(std::move(result)); // second overload
105 \sa emplaceResultAt(), emplaceResult(), addResults()
109 \fn template <typename T> template <typename...Args, std::enable_if_t<std::is_constructible_v<T, Args...>, bool> = true> 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> QPromise<T>::emplaceResult(Args&&...args)
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
117 Returns \c true when the result was added to the collection.
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.
123 These functions only participate in overload resolutions if \c T is
124 constructible from \a args....
126 You can get a result at a specific index by calling QFuture::resultAt().
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().
134 \sa addResult(), addResults()
138 \fn template <typename T> bool QPromise<T>::addResults(const QList<T> &results)
141 Adds \a results at the end of the internal result collection.
143 Returns \c true when \a results are added to the collection.
145 Returns \c false when this promise is in canceled or finished state.
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.
158/*! \fn template<typename T> void QPromise<T>::setException(const QException &e)
160 Sets exception \a e to be the result of the computation.
162 \note You can set at most one exception throughout the computation
165 \note This method must not be used after QFuture::cancel() or
171#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0)
172/*! \fn template<typename T> void QPromise<T>::setException(std::exception_ptr e)
177/*! \fn template<typename T> void QPromise<T>::setException(const std::exception_ptr &e)
183/*! \fn template<typename T> void QPromise<T>::start()
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
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.
193 \sa QFuture::isStarted(), QFuture::waitForFinished(), finish()
196/*! \fn template<typename T> void QPromise<T>::finish()
198 Reports that the computation is finished. Once finished, no new results will
199 be added when calling addResult(). This method accompanies start().
201 \sa QFuture::isFinished(), QFuture::waitForFinished(), start()
204/*! \fn template<typename T> void QPromise<T>::suspendIfRequested()
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().
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.
217 The following code snippets show the usage of suspension mechanism:
219 \snippet snippet_qpromise.cpp suspend_start
221 QFuture::suspend() requests the associated promise to suspend:
223 \snippet snippet_qpromise.cpp suspend_suspend
225 After QFuture::isSuspended() becomes \c true, you can get intermediate
228 \snippet snippet_qpromise.cpp suspend_intermediateResults
230 When suspended, you can resume or cancel the awaiting computation:
232 \snippet snippet_qpromise.cpp suspend_end
235 \sa QFuture::resume(), QFuture::cancel(), QFuture::setSuspended(),
236 QFuture::toggleSuspended()
239/*! \fn template<typename T> bool QPromise<T>::isCanceled() const
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.
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().
249/*! \fn template<typename T> void QPromise<T>::setProgressRange(int minimum, int maximum)
251 Sets the progress range of the computation to be between \a minimum and \a
254 If \a maximum is smaller than \a minimum, \a minimum becomes the only
257 The progress value is reset to be \a minimum.
259 The progress range usage can be disabled by using setProgressRange(0, 0).
260 In this case progress value is also reset to 0.
262 \sa QFuture::progressMinimum(), QFuture::progressMaximum(),
263 QFuture::progressValue()
266/*! \fn template<typename T> void QPromise<T>::setProgressValue(int progressValue)
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()).
272 In case of the \a progressValue falling out of the progress range,
273 this method has no effect.
275 \sa QFuture::progressValue(), setProgressRange()
278/*! \fn template<typename T> void QPromise<T>::setProgressValueAndText(int progressValue, const QString &progressText)
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.
284 \note This function has no effect if the promise is in canceled or finished
287 \sa QFuture::progressValue(), QFuture::progressText(), QFuture::cancel(),
291/*! \fn template<typename T> void QPromise<T>::swap(QPromise<T> &other) noexcept
293 Swaps promise \a other with this promise. This operation is very fast and never fails.