summaryrefslogtreecommitdiffstats
path: root/src/corelib/thread
diff options
context:
space:
mode:
authorSona Kurazyan <sona.kurazyan@qt.io>2020-04-15 11:44:46 +0200
committerSona Kurazyan <sona.kurazyan@qt.io>2020-04-18 12:17:41 +0200
commita7264d9b8c0a50e5ffbf0ea5e7b908637687d9f4 (patch)
treeadbb57746d656e9b4878739c6eaa0339b76d502f /src/corelib/thread
parent3eed6d76b7ce280674caab448682a2e4837cb4d7 (diff)
Make continuations work with move-only types
Use the move-only versions of result reporting and getting operations, if the type of QFuture is not copyable. Task-number: QTBUG-81941 Change-Id: Ic9fa978380e2c24e190e68d974051a650b0e5571 Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Vitaly Fanaskov <vitaly.fanaskov@qt.io>
Diffstat (limited to 'src/corelib/thread')
-rw-r--r--src/corelib/thread/qfuture_impl.h104
1 files changed, 78 insertions, 26 deletions
diff --git a/src/corelib/thread/qfuture_impl.h b/src/corelib/thread/qfuture_impl.h
index 4a57ba7846..5a4ffce1c7 100644
--- a/src/corelib/thread/qfuture_impl.h
+++ b/src/corelib/thread/qfuture_impl.h
@@ -186,6 +186,14 @@ public:
static void create(Function &&func, QFuture<ParentResultType> *f,
QFutureInterface<ResultType> &p, QThreadPool *pool);
+private:
+ void fulfillPromiseWithResult();
+ void fulfillVoidPromise();
+ void fulfillPromiseWithVoidResult();
+
+ template<class... Args>
+ void fulfillPromise(Args &&... args);
+
protected:
virtual void runImpl() = 0;
@@ -193,7 +201,7 @@ protected:
protected:
QFutureInterface<ResultType> promise;
- const QFuture<ParentResultType> parentFuture;
+ QFuture<ParentResultType> parentFuture;
Function function;
};
@@ -269,7 +277,7 @@ private:
private:
QFutureInterface<ResultType> promise;
- const QFuture<ResultType> parentFuture;
+ QFuture<ResultType> parentFuture;
Function handler;
};
@@ -286,32 +294,31 @@ void Continuation<Function, ResultType, ParentResultType>::runFunction()
try {
#endif
if constexpr (!std::is_void_v<ResultType>) {
- if constexpr (std::is_invocable_v<std::decay_t<Function>, QFuture<ParentResultType>>) {
- promise.reportResult(function(parentFuture));
- } else if constexpr (std::is_void_v<ParentResultType>) {
- promise.reportResult(function());
+ if constexpr (std::is_void_v<ParentResultType>) {
+ fulfillPromiseWithVoidResult();
+ } else if constexpr (std::is_invocable_v<Function, ParentResultType>) {
+ fulfillPromiseWithResult();
} else {
// This assert normally should never fail, this is to make sure
// that nothing unexpected happend.
- static_assert(
- std::is_invocable_v<std::decay_t<Function>, std::decay_t<ParentResultType>>,
- "The continuation is not invocable with the provided arguments");
-
- promise.reportResult(function(parentFuture.result()));
+ static_assert(std::is_invocable_v<Function, QFuture<ParentResultType>>,
+ "The continuation is not invocable with the provided arguments");
+ fulfillPromise(parentFuture);
}
} else {
- if constexpr (std::is_invocable_v<std::decay_t<Function>, QFuture<ParentResultType>>) {
- function(parentFuture);
- } else if constexpr (std::is_void_v<ParentResultType>) {
- function();
+ if constexpr (std::is_void_v<ParentResultType>) {
+ if constexpr (std::is_invocable_v<Function, QFuture<void>>)
+ function(parentFuture);
+ else
+ function();
+ } else if constexpr (std::is_invocable_v<Function, ParentResultType>) {
+ fulfillVoidPromise();
} else {
// This assert normally should never fail, this is to make sure
// that nothing unexpected happend.
- static_assert(
- std::is_invocable_v<std::decay_t<Function>, std::decay_t<ParentResultType>>,
- "The continuation is not invocable with the provided arguments");
-
- function(parentFuture.result());
+ static_assert(std::is_invocable_v<Function, QFuture<ParentResultType>>,
+ "The continuation is not invocable with the provided arguments");
+ function(parentFuture);
}
}
#ifndef QT_NO_EXCEPTIONS
@@ -426,6 +433,43 @@ void Continuation<Function, ResultType, ParentResultType>::create(Function &&fun
f->d.setContinuation(continuation);
}
+template<typename Function, typename ResultType, typename ParentResultType>
+void Continuation<Function, ResultType, ParentResultType>::fulfillPromiseWithResult()
+{
+ if constexpr (std::is_copy_constructible_v<ParentResultType>)
+ fulfillPromise(parentFuture.result());
+ else
+ fulfillPromise(parentFuture.takeResult());
+}
+
+template<typename Function, typename ResultType, typename ParentResultType>
+void Continuation<Function, ResultType, ParentResultType>::fulfillVoidPromise()
+{
+ if constexpr (std::is_copy_constructible_v<ParentResultType>)
+ function(parentFuture.result());
+ else
+ function(parentFuture.takeResult());
+}
+
+template<typename Function, typename ResultType, typename ParentResultType>
+void Continuation<Function, ResultType, ParentResultType>::fulfillPromiseWithVoidResult()
+{
+ if constexpr (std::is_invocable_v<Function, QFuture<void>>)
+ fulfillPromise(parentFuture);
+ else
+ fulfillPromise();
+}
+
+template<typename Function, typename ResultType, typename ParentResultType>
+template<class... Args>
+void Continuation<Function, ResultType, ParentResultType>::fulfillPromise(Args &&... args)
+{
+ if constexpr (std::is_copy_constructible_v<ResultType>)
+ promise.reportResult(std::invoke(function, std::forward<Args>(args)...));
+ else
+ promise.reportAndMoveResult(std::invoke(function, std::forward<Args>(args)...));
+}
+
#ifndef QT_NO_EXCEPTIONS
template<class Function, class ResultType>
@@ -460,8 +504,12 @@ void FailureHandler<Function, ResultType>::run()
handleException<ArgType>();
}
} else {
- if constexpr (!std::is_void_v<ResultType>)
- promise.reportResult(parentFuture.result());
+ if constexpr (!std::is_void_v<ResultType>) {
+ if constexpr (std::is_copy_constructible_v<ResultType>)
+ promise.reportResult(parentFuture.result());
+ else
+ promise.reportAndMoveResult(parentFuture.takeResult());
+ }
}
promise.reportFinished();
}
@@ -478,7 +526,10 @@ void FailureHandler<Function, ResultType>::handleException()
if constexpr (std::is_void_v<ResultType>) {
handler(e);
} else {
- promise.reportResult(handler(e));
+ if constexpr (std::is_copy_constructible_v<ResultType>)
+ promise.reportResult(handler(e));
+ else
+ promise.reportAndMoveResult(handler(e));
}
} catch (...) {
promise.reportException(std::current_exception());
@@ -497,11 +548,12 @@ void FailureHandler<Function, ResultType>::handleAllExceptions()
parentFuture.d.exceptionStore().throwPossibleException();
} catch (...) {
try {
- if constexpr (std::is_void_v<ResultType>) {
+ if constexpr (std::is_void_v<ResultType>)
handler();
- } else {
+ else if constexpr (std::is_copy_constructible_v<ResultType>)
promise.reportResult(handler());
- }
+ else
+ promise.reportAndMoveResult(handler());
} catch (...) {
promise.reportException(std::current_exception());
}