summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorIvan Solovev <ivan.solovev@qt.io>2020-11-12 18:02:09 +0100
committerIvan Solovev <ivan.solovev@qt.io>2020-11-23 09:50:21 +0100
commit54875be84de059374920e4c0deacd13a41caaa13 (patch)
tree3fd95411cda0b2d0e21ae749d7133c96323c9131 /src
parentf61f8bb966fdc04662fb4e6597698b573fcb8b94 (diff)
Add convenience functions for QFuture creation
[ChangeLog][QtCore][QFuture] Add convenience functions to create a ready QFuture and a QFuture with an exception Task-number: QTBUG-86713 Change-Id: Ic7f9ca590a8ea8a9696b84f35bad074780794461 Reviewed-by: MÃ¥rten Nordheim <marten.nordheim@qt.io> Reviewed-by: Sona Kurazyan <sona.kurazyan@qt.io>
Diffstat (limited to 'src')
-rw-r--r--src/corelib/thread/qfuture.qdoc108
-rw-r--r--src/corelib/thread/qfuture_impl.h63
2 files changed, 170 insertions, 1 deletions
diff --git a/src/corelib/thread/qfuture.qdoc b/src/corelib/thread/qfuture.qdoc
index 82b7657016..7603fe2230 100644
--- a/src/corelib/thread/qfuture.qdoc
+++ b/src/corelib/thread/qfuture.qdoc
@@ -134,7 +134,12 @@
you can attach multiple continuations to a signal, which are invoked in the
same thread or a new thread.
- \sa QtFuture::connect(), QFutureWatcher, {Qt Concurrent}
+ A ready QFuture object with a value or a QFuture object holding exception can
+ be created using convenience functions QtFuture::makeReadyFuture and
+ QtFuture::makeExceptionalFuture.
+
+ \sa QtFuture::connect(), QtFuture::makeReadyFuture(),
+ QtFuture::makeExceptionalFuture(), QFutureWatcher, {Qt Concurrent}
*/
/*! \fn template <typename T> QFuture<T>::QFuture()
@@ -944,6 +949,107 @@
\sa QFuture, QFuture::then()
*/
+/*! \fn template<typename T> static QFuture<std::decay_t<T>> QtFuture::makeReadyFuture(T &&value)
+
+ \since 6.1
+ \overload
+
+ Creates and returns a QFuture which already has a result \a value.
+ The returned QFuture has a type of std::decay_t<T>, where T is not void.
+
+ \code
+ auto f = QtFuture::makeReadyFuture(std::make_unique<int>(42));
+ ...
+ const int result = *f.takeResult(); // result == 42
+ \endcode
+
+ \sa QFuture, QtFuture::makeExceptionalFuture()
+*/
+
+/*! \fn QFuture<void> QtFuture::makeReadyFuture()
+
+ \since 6.1
+ \overload
+
+ Creates and returns a void QFuture. Such QFuture can't store any result.
+ One can use it to query the state of the computation.
+ The returned QFuture will always be in the finished state.
+
+ \code
+ auto f = QtFuture::makeReadyFuture();
+ ...
+ const bool started = f.isStarted(); // started == true
+ const bool running = f.isRunning(); // running == false
+ const bool finished = f.isFinished(); // finished == true
+ \endcode
+
+ \sa QFuture, QFuture::isStarted(), QFuture::isRunning(),
+ QFuture::isFinished(), QtFuture::makeExceptionalFuture()
+*/
+
+/*! \fn template<typename T> static QFuture<T> QtFuture::makeReadyFuture(const QList<T> &values)
+
+ \since 6.1
+ \overload
+
+ Creates and returns a QFuture which already has multiple results set from \a values.
+
+ \code
+ const QList<int> values { 1, 2, 3 };
+ auto f = QtFuture::makeReadyFuture(values);
+ ...
+ const int count = f.resultCount(); // count == 3
+ const auto results = f.results(); // results == { 1, 2, 3 }
+ \endcode
+
+ \sa QFuture, QtFuture::makeExceptionalFuture()
+*/
+
+/*! \fn template<typename T> static QFuture<T> QtFuture::makeExceptionalFuture(const QException &exception)
+
+ \since 6.1
+
+ Creates and returns a QFuture which already has an exception \a exception.
+
+ \code
+ QException e;
+ auto f = QtFuture::makeExceptionalFuture<int>(e);
+ ...
+ try {
+ f.result(); // throws QException
+ } catch (QException &) {
+ // handle exception here
+ }
+ \endcode
+
+ \sa QFuture, QException, QtFuture::makeReadyFuture()
+*/
+
+/*! \fn template<typename T> static QFuture<T> QtFuture::makeExceptionalFuture(std::exception_ptr exception)
+
+ \since 6.1
+ \overload
+
+ Creates and returns a QFuture which already has an exception \a exception.
+
+ \code
+ struct TestException
+ {
+ };
+ ...
+ auto exception = std::make_exception_ptr(TestException());
+ auto f = QtFuture::makeExceptionalFuture<int>(exception);
+ ...
+ try {
+ f.result(); // throws TestException
+ } catch (TestException &) {
+ // handle exception here
+ }
+ \endcode
+
+ \sa QFuture, QException, QtFuture::makeReadyFuture()
+*/
+
/*! \fn template<class T> template<class Function> QFuture<typename QFuture<T>::ResultType<Function>> QFuture<T>::then(Function &&function)
\since 6.0
diff --git a/src/corelib/thread/qfuture_impl.h b/src/corelib/thread/qfuture_impl.h
index b8b9f39951..1a02cc9cf1 100644
--- a/src/corelib/thread/qfuture_impl.h
+++ b/src/corelib/thread/qfuture_impl.h
@@ -49,6 +49,7 @@
#include <QtCore/qglobal.h>
#include <QtCore/qfutureinterface.h>
#include <QtCore/qthreadpool.h>
+#include <QtCore/qexception.h>
QT_BEGIN_NAMESPACE
@@ -741,6 +742,68 @@ static QFuture<ArgsType<Signal>> connect(Sender *sender, Signal signal)
return promise.future();
}
+template<typename T, typename = QtPrivate::EnableForNonVoid<T>>
+static QFuture<std::decay_t<T>> makeReadyFuture(T &&value)
+{
+ QFutureInterface<std::decay_t<T>> promise;
+ promise.reportStarted();
+ promise.reportResult(std::forward<T>(value));
+ promise.reportFinished();
+
+ return promise.future();
+}
+
+#if defined(Q_CLANG_QDOC)
+static QFuture<void> makeReadyFuture()
+#else
+template<typename T = void>
+static QFuture<T> makeReadyFuture()
+#endif
+{
+ QFutureInterface<T> promise;
+ promise.reportStarted();
+ promise.reportFinished();
+
+ return promise.future();
+}
+
+template<typename T>
+static QFuture<T> makeReadyFuture(const QList<T> &values)
+{
+ QFutureInterface<T> promise;
+ promise.reportStarted();
+ promise.reportResults(values);
+ promise.reportFinished();
+
+ return promise.future();
+}
+
+#ifndef QT_NO_EXCEPTIONS
+
+template<typename T = void>
+static QFuture<T> makeExceptionalFuture(std::exception_ptr exception)
+{
+ QFutureInterface<T> promise;
+ promise.reportStarted();
+ promise.reportException(exception);
+ promise.reportFinished();
+
+ return promise.future();
+}
+
+template<typename T = void>
+static QFuture<T> makeExceptionalFuture(const QException &exception)
+{
+ try {
+ exception.raise();
+ } catch (...) {
+ return makeExceptionalFuture<T>(std::current_exception());
+ }
+ Q_UNREACHABLE();
+}
+
+#endif // QT_NO_EXCEPTIONS
+
} // namespace QtFuture
QT_END_NAMESPACE