diff options
author | Ivan Solovev <ivan.solovev@qt.io> | 2020-11-12 18:02:09 +0100 |
---|---|---|
committer | Ivan Solovev <ivan.solovev@qt.io> | 2020-11-23 09:50:21 +0100 |
commit | 54875be84de059374920e4c0deacd13a41caaa13 (patch) | |
tree | 3fd95411cda0b2d0e21ae749d7133c96323c9131 /src | |
parent | f61f8bb966fdc04662fb4e6597698b573fcb8b94 (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.qdoc | 108 | ||||
-rw-r--r-- | src/corelib/thread/qfuture_impl.h | 63 |
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 |