Revision control
++ // Copyright (C) 2020 The Qt Company Ltd.
++ // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
++
++ /*! \class QPromise
++ \inmodule QtCore
++ \threadsafe
++ \brief The QPromise class provides a way to store computation results to be accessed by QFuture.
++ \since 6.0
++
++ \ingroup thread
++
++ QPromise is a template class where the template parameter \a T specifies
++ the result type that can be stored and later accessed via QFuture.
++
++ QPromise provides a simple way to communicate progress and results of the
++ user-defined computation to QFuture in an asynchronous fashion. For the
++ communication to work, QFuture must be constructed by QPromise.
++
++ You can use QPromise based workloads as an alternative to \l {Qt Concurrent}
++ framework when fine-grained control is needed or high-level communication
++ primitive to accompany QFuture is sufficient.
++
++ The simplest case of promise and future collaboration would be a single
++ result communication:
++
++ \snippet snippet_qpromise.cpp basic
++
++ By design, QPromise is a move-only object. This behavior helps to ensure
++ that whenever the promise is destroyed, the associated future object is
++ notified and will not wait forever for the results to become available.
++ However, this is inconvenient if one wants to use the same promise to report
++ results from different threads. There is no specific way to do that at the
++ moment, but known mechanisms exist, such as the use of smart pointers or raw
++ pointers/references. QSharedPointer is a good default choice if you want to
++ copy your promise and use it in multiple places simultaneously. Raw pointers
++ or references are, in a sense, easier, and probably perform better (since
++ there is no need to do a resource management) but may lead to dangling.
++
++ Here is an example of how a promise can be used in multiple threads:
++
++ \snippet snippet_qpromise.cpp multithread_init
++ \codeline
++ \snippet snippet_qpromise.cpp multithread_main
++ \codeline
++ \snippet snippet_qpromise.cpp multithread_cleanup
++
++ \sa QFuture
++ */
++
++ /*! \fn template <typename T> QPromise<T>::QPromise()
++
++ Constructs a QPromise with a default state.
++ */
++
++ /*! \fn template <typename T> QPromise<T>::QPromise(QPromise<T> &&other)
++
++ Move constructs a new QPromise from \a other.
++
++ \sa operator=()
++ */
++
++ /*! \fn template <typename T> QPromise<T>::QPromise(const QFutureInterface<T> &other)
++ \fn template <typename T> QPromise<T>::QPromise(QFutureInterface<T> &&other) noexcept
++
++ \internal
++ Constructs a QPromise with a passed QFutureInterface \a other.
++ Used internally for QtConcurrent::run(), when its callable takes
++ a reference to the associated promise as its first argument
++ (run with promise mode).
++
++ \sa operator=()
++ */
++
++
++ /*! \fn template <typename T> QPromise<T> &QPromise<T>::operator=(QPromise<T> &&other)
++
++ Move assigns \a other to this promise and returns a reference to this
++ promise.
++ */
++
++ /*! \fn template <typename T> QPromise<T>::~QPromise()
++
++ Destroys the promise.
++
++ \note The promise implicitly transitions to a canceled state on destruction
++ unless finish() is called beforehand by the user.
++ */
++
++ /*! \fn template <typename T> QFuture<T> QPromise<T>::future() const
++
++ Returns a future associated with this promise.
++ */
++
++ /*! \fn template <typename T> bool QPromise<T>::addResult(const T &result, int index = -1)
++ \fn template <typename T> bool QPromise<T>::addResult(T &&result, int index = -1)
++
++ Same as
++ \code
++ emplaceResultAt(index, result); // first overload
++ emplaceResultAt(index, std::move(result)); // second overload
++ \endcode
++ or, if \c{index == -1} (the default)
++ \code
++ emplaceResult(result); // first overload
++ emplaceResult(std::move(result)); // second overload
++ \endcode
++
++ \sa emplaceResultAt(), emplaceResult(), addResults()
++ */
++
++ /*!
++ \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)
++ \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)
++ \since 6.6
++
++ Adds a result constructed from \a args... to the internal result collection
++ at \a index position (emplaceResultAt()) or the end of the collection
++ (emplaceResult()).
++
++ Returns \c true when the result was added to the collection.
++
++ Returns \c false when this promise is in canceled or finished state or when
++ the result was rejected. addResult() rejects to add a result if there's already
++ another result in the collection stored at the same index.
++
++ These functions only participate in overload resolutions if \c T is
++ constructible from \a args....
++
++ You can get a result at a specific index by calling QFuture::resultAt().
++
++ \note It is possible to specify an arbitrary index and request result at
++ that index. However, some QFuture methods operate with continuous results.
++ For instance, iterative approaches that use QFuture::resultCount() or
++ QFuture::const_iterator. In order to get all available results without
++ thinking if there are index gaps or not, use QFuture::results().
++
++ \sa addResult(), addResults()
++ */
++
++ /*!
++ \fn template <typename T> bool QPromise<T>::addResults(const QList<T> &results)
++ \since 6.6
++
++ Adds \a results at the end of the internal result collection.
++
++ Returns \c true when \a results are added to the collection.
++
++ Returns \c false when this promise is in canceled or finished state.
++
++ This is more efficient than looping over addResult(), because associated
++ futures will be notified only once per addResults() call, instead of once
++ per element contained in \a results, as would be the case with individual
++ addResult() calls. But if the calculation of each element takes time, then
++ the code on the receiving end (future) cannot make progress until all
++ results are reported, so use this function only if the calculation of
++ consecutive elements is relatively fast.
++
++ \sa addResult()
++ */
++
++ /*! \fn template<typename T> void QPromise<T>::setException(const QException &e)
++
++ Sets exception \a e to be the result of the computation.
++
++ \note You can set at most one exception throughout the computation
++ execution.
++
++ \note This method has no effect after QFuture::cancel() or
++ finish().
++
++ \sa isCanceled()
++ */
++
++ #if QT_VERSION < QT_VERSION_CHECK(7, 0, 0)
++ /*! \fn template<typename T> void QPromise<T>::setException(std::exception_ptr e)
++
++ \overload
++ */
++ #else
++ /*! \fn template<typename T> void QPromise<T>::setException(const std::exception_ptr &e)
++
++ \overload
++ */
++ #endif
++
++ /*! \fn template<typename T> void QPromise<T>::start()
++
++ Reports that the computation is started. Calling this method is important to
++ state the beginning of the computation as QFuture methods rely on this
++ information.
++
++ \note Extra attention is required when start() is called from a
++ newly created thread. In such case, the call might naturally be delayed due
++ to the implementation details of the thread scheduling.
++
++ \sa QFuture::isStarted(), QFuture::waitForFinished(), finish()
++ */
++
++ /*! \fn template<typename T> void QPromise<T>::finish()
++
++ Reports that the computation is finished. Once finished, no new results will
++ be added when calling addResult(). This method accompanies start().
++
++ \sa QFuture::isFinished(), QFuture::waitForFinished(), start()
++ */
++
++ /*! \fn template<typename T> void QPromise<T>::suspendIfRequested()
++
++ Conditionally suspends current thread of execution and waits until resumed
++ or canceled by the corresponding methods of QFuture. This method does not
++ block unless the computation is requested to be suspended by
++ QFuture::suspend() or another related method. If you want to check that the
++ execution has been suspended, use QFuture::isSuspended().
++
++ \note When using the same promise in multiple threads,
++ QFuture::isSuspended() becomes \c true as soon as at least one thread with
++ the promise suspends.
++
++
++ The following code snippets show the usage of suspension mechanism:
++
++ \snippet snippet_qpromise.cpp suspend_start
++
++ QFuture::suspend() requests the associated promise to suspend:
++
++ \snippet snippet_qpromise.cpp suspend_suspend
++
++ After QFuture::isSuspended() becomes \c true, you can get intermediate
++ results:
++
++ \snippet snippet_qpromise.cpp suspend_intermediateResults
++
++ When suspended, you can resume or cancel the awaiting computation:
++
++ \snippet snippet_qpromise.cpp suspend_end
++
++
++ \sa QFuture::resume(), QFuture::cancel(), QFuture::setSuspended(),
++ QFuture::toggleSuspended()
++ */
++
++ /*! \fn template<typename T> bool QPromise<T>::isCanceled() const
++
++ Returns whether the computation has been canceled with the
++ QFuture::cancel() function. The returned value \c true indicates that the
++ computation should be finished and finish() called.
++
++ \note After cancellation, results currently available may still be accessed
++ by a future, but new results will not be added when calling addResult().
++ */
++
++ /*! \fn template<typename T> void QPromise<T>::setProgressRange(int minimum, int maximum)
++
++ Sets the progress range of the computation to be between \a minimum and \a
++ maximum.
++
++ If \a maximum is smaller than \a minimum, \a minimum becomes the only
++ legal value.
++
++ The progress value is reset to be \a minimum.
++
++ The progress range usage can be disabled by using setProgressRange(0, 0).
++ In this case progress value is also reset to 0.
++
++ \sa QFuture::progressMinimum(), QFuture::progressMaximum(),
++ QFuture::progressValue()
++ */
++
++ /*! \fn template<typename T> void QPromise<T>::setProgressValue(int progressValue)
++
++ Sets the progress value of the computation to \a progressValue. It is
++ possible to only increment the progress value. This is a convenience method
++ for calling setProgressValueAndText(progressValue, QString()).
++
++ In case of the \a progressValue falling out of the progress range,
++ this method has no effect.
++
++ \sa QFuture::progressValue(), setProgressRange()
++ */
++
++ /*! \fn template<typename T> void QPromise<T>::setProgressValueAndText(int progressValue, const QString &progressText)
++
++ Sets the progress value and the progress text of the computation to \a
++ progressValue and \a progressText respectively. It is possible to only
++ increment the progress value.
++
++ \note This function has no effect if the promise is in canceled or finished
++ state.
++
++ \sa QFuture::progressValue(), QFuture::progressText(), QFuture::cancel(),
++ finish()
++ */
++
++ /*! \fn template<typename T> void QPromise<T>::swap(QPromise<T> &other) noexcept
++ \memberswap{promise}
++ */