diff options
author | Sona Kurazyan <sona.kurazyan@qt.io> | 2022-04-06 13:03:12 +0200 |
---|---|---|
committer | Sona Kurazyan <sona.kurazyan@qt.io> | 2022-04-21 20:25:13 +0000 |
commit | 9eb090d6835e436627c7a6b00e2ee97933847345 (patch) | |
tree | 0a5c210d0a39982648f0bde721141ad6d628b2d1 /src/corelib/thread/qfuture_impl.h | |
parent | f08fd3c05565f8cb170b0314a891bc1b515196e8 (diff) |
Add support for unwrapping QFuture<QFuture<T>>
Added QFuture::unwrap() for unwrapping the future nested inside
QFuture<QFuture<T>>. QTBUG-86725 suggests doing the unwrapping
automatically inside .then(), but this will change the return type
of .then() that used to return QFuture<QFuture<T>> and might cause
SC breaks. Apart from that, QFuture::unwrap() might be helpful in
general, for asynchronous computations that return a nested QFuture.
[ChangeLog][QtCore][QFuture] Added QFuture::unwrap() for unwrapping the
future nested inside QFuture<QFuture<T>>.
Task-number: QTBUG-86725
Change-Id: I8886743aca261dca46f62d9dfcaead4a141d3dc4
Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
Diffstat (limited to 'src/corelib/thread/qfuture_impl.h')
-rw-r--r-- | src/corelib/thread/qfuture_impl.h | 53 |
1 files changed, 53 insertions, 0 deletions
diff --git a/src/corelib/thread/qfuture_impl.h b/src/corelib/thread/qfuture_impl.h index e4b0ea6289..5a70659c1d 100644 --- a/src/corelib/thread/qfuture_impl.h +++ b/src/corelib/thread/qfuture_impl.h @@ -867,6 +867,59 @@ public: } }; +struct UnwrapHandler +{ + template<class T> + static auto unwrapImpl(T *outer) + { + Q_ASSERT(outer); + + using ResultType = typename QtPrivate::Future<std::decay_t<T>>::type; + using NestedType = typename QtPrivate::Future<ResultType>::type; + QFutureInterface<NestedType> promise(QFutureInterfaceBase::State::Pending); + + outer->then([promise](const QFuture<ResultType> &outerFuture) mutable { + // We use the .then([](QFuture<ResultType> outerFuture) {...}) version + // (where outerFuture == *outer), to propagate the exception if the + // outer future has failed. + Q_ASSERT(outerFuture.isFinished()); +#ifndef QT_NO_EXCEPTIONS + if (outerFuture.d.hasException()) { + promise.reportStarted(); + promise.reportException(outerFuture.d.exceptionStore().exception()); + promise.reportFinished(); + return; + } +#endif + + promise.reportStarted(); + ResultType nestedFuture = outerFuture.result(); + + nestedFuture.then([promise] (const QFuture<NestedType> &nested) mutable { +#ifndef QT_NO_EXCEPTIONS + if (nested.d.hasException()) { + promise.reportException(nested.d.exceptionStore().exception()); + } else +#endif + { + if constexpr (!std::is_void_v<NestedType>) + promise.reportResults(nested.results()); + } + promise.reportFinished(); + }).onCanceled([promise] () mutable { + promise.reportCanceled(); + promise.reportFinished(); + }); + }).onCanceled([promise]() mutable { + // propagate the cancellation of the outer future + promise.reportStarted(); + promise.reportCanceled(); + promise.reportFinished(); + }); + return promise.future(); + } +}; + } // namespace QtPrivate namespace QtFuture { |