diff options
author | Sona Kurazyan <sona.kurazyan@qt.io> | 2020-05-05 17:44:47 +0200 |
---|---|---|
committer | Sona Kurazyan <sona.kurazyan@qt.io> | 2020-05-15 22:35:30 +0200 |
commit | 1a5cc8d13d0d348a571cab0d24dc814b896c8db7 (patch) | |
tree | f61154e733d74c5709549971bb7ce2edeb4ab453 /src/corelib/thread/qfuture_impl.h | |
parent | 612f6999c81a500a024f128bdf739342d659754a (diff) |
Add support of cancellation handler callbacks to QFuture
Added QFuture::onCanceled() method, for attaching handlers to be called
when the QFuture gets canceled.
Change-Id: I1f01647d6173ba0c1db6641e14140108b33ac7c4
Reviewed-by: Leena Miettinen <riitta-leena.miettinen@qt.io>
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Diffstat (limited to 'src/corelib/thread/qfuture_impl.h')
-rw-r--r-- | src/corelib/thread/qfuture_impl.h | 75 |
1 files changed, 63 insertions, 12 deletions
diff --git a/src/corelib/thread/qfuture_impl.h b/src/corelib/thread/qfuture_impl.h index 0e0cef0dbf..82c89cfa38 100644 --- a/src/corelib/thread/qfuture_impl.h +++ b/src/corelib/thread/qfuture_impl.h @@ -495,6 +495,28 @@ void Continuation<Function, ResultType, ParentResultType>::fulfillPromise(Args & promise.reportAndMoveResult(std::invoke(function, std::forward<Args>(args)...)); } +template<class T> +void fulfillPromise(QFutureInterface<T> &promise, QFuture<T> &future) +{ + if constexpr (!std::is_void_v<T>) { + if constexpr (std::is_copy_constructible_v<T>) + promise.reportResult(future.result()); + else + promise.reportAndMoveResult(future.takeResult()); + } +} + +template<class T, class Function> +void fulfillPromise(QFutureInterface<T> &promise, Function &&handler) +{ + if constexpr (std::is_void_v<T>) + handler(); + else if constexpr (std::is_copy_constructible_v<T>) + promise.reportResult(handler()); + else + promise.reportAndMoveResult(handler()); +} + #ifndef QT_NO_EXCEPTIONS template<class Function, class ResultType> @@ -529,12 +551,7 @@ void FailureHandler<Function, ResultType>::run() handleException<ArgType>(); } } else { - if constexpr (!std::is_void_v<ResultType>) { - if constexpr (std::is_copy_constructible_v<ResultType>) - promise.reportResult(parentFuture.result()); - else - promise.reportAndMoveResult(parentFuture.takeResult()); - } + QtPrivate::fulfillPromise(promise, parentFuture); } promise.reportFinished(); } @@ -573,12 +590,7 @@ void FailureHandler<Function, ResultType>::handleAllExceptions() parentFuture.d.exceptionStore().throwPossibleException(); } catch (...) { try { - if constexpr (std::is_void_v<ResultType>) - handler(); - else if constexpr (std::is_copy_constructible_v<ResultType>) - promise.reportResult(handler()); - else - promise.reportAndMoveResult(handler()); + QtPrivate::fulfillPromise(promise, std::forward<Function>(handler)); } catch (...) { promise.reportException(std::current_exception()); } @@ -587,6 +599,45 @@ void FailureHandler<Function, ResultType>::handleAllExceptions() #endif // QT_NO_EXCEPTIONS +template<class Function, class ResultType> +class CanceledHandler +{ +public: + static QFuture<ResultType> create(Function &&handler, QFuture<ResultType> *future, + QFutureInterface<ResultType> promise) + { + Q_ASSERT(future); + + auto canceledContinuation = [parentFuture = *future, promise, + handler = std::move(handler)]() mutable { + promise.reportStarted(); + + if (parentFuture.isCanceled()) { +#ifndef QT_NO_EXCEPTIONS + if (parentFuture.d.exceptionStore().hasException()) { + // Propagate the exception to the result future + promise.reportException(parentFuture.d.exceptionStore().exception()); + } else { + try { +#endif + QtPrivate::fulfillPromise(promise, std::forward<Function>(handler)); +#ifndef QT_NO_EXCEPTIONS + } catch (...) { + promise.reportException(std::current_exception()); + } + } +#endif + } else { + QtPrivate::fulfillPromise(promise, parentFuture); + } + + promise.reportFinished(); + }; + future->d.setContinuation(std::move(canceledContinuation)); + return promise.future(); + } +}; + } // namespace QtPrivate namespace QtFuture { |