summaryrefslogtreecommitdiffstats
path: root/src/corelib/thread/qfuture_impl.h
diff options
context:
space:
mode:
authorSona Kurazyan <sona.kurazyan@qt.io>2020-05-05 17:44:47 +0200
committerSona Kurazyan <sona.kurazyan@qt.io>2020-05-15 22:35:30 +0200
commit1a5cc8d13d0d348a571cab0d24dc814b896c8db7 (patch)
treef61154e733d74c5709549971bb7ce2edeb4ab453 /src/corelib/thread/qfuture_impl.h
parent612f6999c81a500a024f128bdf739342d659754a (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.h75
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 {