summaryrefslogtreecommitdiffstats
path: root/src/corelib/thread/qfuture_impl.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/corelib/thread/qfuture_impl.h')
-rw-r--r--src/corelib/thread/qfuture_impl.h80
1 files changed, 37 insertions, 43 deletions
diff --git a/src/corelib/thread/qfuture_impl.h b/src/corelib/thread/qfuture_impl.h
index 53f2326cde..351093adc7 100644
--- a/src/corelib/thread/qfuture_impl.h
+++ b/src/corelib/thread/qfuture_impl.h
@@ -11,11 +11,9 @@
#endif
#include <QtCore/qglobal.h>
-#include <QtCore/qbasicfuturewatcher.h>
#include <QtCore/qfutureinterface.h>
#include <QtCore/qthreadpool.h>
#include <QtCore/qexception.h>
-#include <QtCore/qpointer.h>
#include <QtCore/qpromise.h>
#include <memory>
@@ -289,6 +287,7 @@ using IsForwardIterable =
template<typename Function, typename ResultType, typename ParentResultType>
class Continuation
{
+ Q_DISABLE_COPY_MOVE(Continuation)
public:
template<typename F = Function>
Continuation(F &&func, const QFuture<ParentResultType> &f, QPromise<ResultType> &&p)
@@ -536,18 +535,18 @@ void Continuation<Function, ResultType, ParentResultType>::create(F &&func,
fi.setLaunchAsync(launchAsync);
- auto continuation = [func = std::forward<F>(func), fi, promise = QPromise(fi), pool,
+ auto continuation = [func = std::forward<F>(func), fi, promise_ = QPromise(fi), pool,
launchAsync](const QFutureInterfaceBase &parentData) mutable {
const auto parent = QFutureInterface<ParentResultType>(parentData).future();
Continuation<Function, ResultType, ParentResultType> *continuationJob = nullptr;
if (launchAsync) {
auto asyncJob = new AsyncContinuation<Function, ResultType, ParentResultType>(
- std::forward<Function>(func), parent, std::move(promise), pool);
+ std::forward<Function>(func), parent, std::move(promise_), pool);
fi.setRunnable(asyncJob);
continuationJob = asyncJob;
} else {
continuationJob = new SyncContinuation<Function, ResultType, ParentResultType>(
- std::forward<Function>(func), parent, std::move(promise));
+ std::forward<Function>(func), parent, std::move(promise_));
}
bool isLaunched = continuationJob->execute();
@@ -574,11 +573,11 @@ void Continuation<Function, ResultType, ParentResultType>::create(F &&func,
fi.setLaunchAsync(true);
fi.setThreadPool(pool);
- auto continuation = [func = std::forward<F>(func), promise = QPromise(fi),
+ auto continuation = [func = std::forward<F>(func), promise_ = QPromise(fi),
pool](const QFutureInterfaceBase &parentData) mutable {
const auto parent = QFutureInterface<ParentResultType>(parentData).future();
auto continuationJob = new AsyncContinuation<Function, ResultType, ParentResultType>(
- std::forward<Function>(func), parent, std::move(promise), pool);
+ std::forward<Function>(func), parent, std::move(promise_), pool);
bool isLaunched = continuationJob->execute();
// If continuation is successfully launched, AsyncContinuation will be deleted
// by the QThreadPool which has started it.
@@ -590,6 +589,15 @@ void Continuation<Function, ResultType, ParentResultType>::create(F &&func,
f->d.setContinuation(ContinuationWrapper(std::move(continuation)), fi.d);
}
+template <typename Continuation>
+void watchContinuation(const QObject *context, Continuation &&c, QFutureInterfaceBase &fi)
+{
+ using Prototype = typename QtPrivate::Callable<Continuation>::Function;
+ watchContinuationImpl(context,
+ QtPrivate::makeCallableObject<Prototype>(std::forward<Continuation>(c)),
+ fi);
+}
+
template<typename Function, typename ResultType, typename ParentResultType>
template<typename F>
void Continuation<Function, ResultType, ParentResultType>::create(F &&func,
@@ -604,21 +612,13 @@ void Continuation<Function, ResultType, ParentResultType>::create(F &&func,
// continuation callback is destroyed. The promise that is created in the capture list is
// destroyed and, if it is not yet finished, cancelled.
auto continuation = [func = std::forward<F>(func), parent = *f,
- promise = QPromise(fi)]() mutable {
+ promise_ = QPromise(fi)]() mutable {
SyncContinuation<Function, ResultType, ParentResultType> continuationJob(
- std::forward<Function>(func), parent, std::move(promise));
+ std::forward<Function>(func), parent, std::move(promise_));
continuationJob.execute();
};
- auto *watcher = new QBasicFutureWatcher;
- watcher->moveToThread(context->thread());
- QObject::connect(watcher, &QBasicFutureWatcher::finished,
- context, std::move(continuation));
- QObject::connect(watcher, &QBasicFutureWatcher::finished,
- watcher, &QObject::deleteLater);
- QObject::connect(context, &QObject::destroyed,
- watcher, &QObject::deleteLater);
- watcher->setFuture(f->d);
+ QtPrivate::watchContinuation(context, std::move(continuation), f->d);
}
template<typename Function, typename ResultType, typename ParentResultType>
@@ -684,11 +684,11 @@ void FailureHandler<Function, ResultType>::create(F &&function, QFuture<ResultTy
{
Q_ASSERT(future);
- auto failureContinuation = [function = std::forward<F>(function), promise = QPromise(fi)](
+ auto failureContinuation = [function = std::forward<F>(function), promise_ = QPromise(fi)](
const QFutureInterfaceBase &parentData) mutable {
const auto parent = QFutureInterface<ResultType>(parentData).future();
FailureHandler<Function, ResultType> failureHandler(std::forward<Function>(function),
- parent, std::move(promise));
+ parent, std::move(promise_));
failureHandler.run();
};
@@ -704,18 +704,13 @@ void FailureHandler<Function, ResultType>::create(F &&function, QFuture<ResultTy
Q_ASSERT(future);
Q_ASSERT(context);
auto failureContinuation = [function = std::forward<F>(function),
- parent = *future, promise = QPromise(fi)]() mutable {
+ parent = *future, promise_ = QPromise(fi)]() mutable {
FailureHandler<Function, ResultType> failureHandler(
- std::forward<Function>(function), parent, std::move(promise));
+ std::forward<Function>(function), parent, std::move(promise_));
failureHandler.run();
};
- auto *watcher = new QBasicFutureWatcher;
- watcher->moveToThread(context->thread());
- QObject::connect(watcher, &QBasicFutureWatcher::finished, context, std::move(failureContinuation));
- QObject::connect(watcher, &QBasicFutureWatcher::finished, watcher, &QObject::deleteLater);
- QObject::connect(context, &QObject::destroyed, watcher, &QObject::deleteLater);
- watcher->setFuture(future->d);
+ QtPrivate::watchContinuation(context, std::move(failureContinuation), future->d);
}
template<class Function, class ResultType>
@@ -732,6 +727,8 @@ void FailureHandler<Function, ResultType>::run()
} else {
handleException<ArgType>();
}
+ } else if (parentFuture.d.isChainCanceled()) {
+ promise.future().cancel();
} else {
QtPrivate::fulfillPromise(promise, parentFuture);
}
@@ -807,13 +804,7 @@ public:
run(std::forward<F>(handler), parentFuture, std::move(promise));
};
- auto *watcher = new QBasicFutureWatcher;
- watcher->moveToThread(context->thread());
- QObject::connect(watcher, &QBasicFutureWatcher::finished,
- context, std::move(canceledContinuation));
- QObject::connect(watcher, &QBasicFutureWatcher::finished, watcher, &QObject::deleteLater);
- QObject::connect(context, &QObject::destroyed, watcher, &QObject::deleteLater);
- watcher->setFuture(future->d);
+ QtPrivate::watchContinuation(context, std::move(canceledContinuation), future->d);
}
template<class F = Function>
@@ -1016,7 +1007,7 @@ Q_CORE_EXPORT QFuture<void> makeReadyVoidFuture(); // implemented in qfutureinte
#if QT_DEPRECATED_SINCE(6, 10)
template<typename T, typename = QtPrivate::EnableForNonVoid<T>>
-QT_DEPRECATED_VERSION_X(6, 10, "Use makeReadyValueFuture() instead")
+QT_DEPRECATED_VERSION_X(6, 10, "Use makeReadyValueFuture() instead.")
static QFuture<std::decay_t<T>> makeReadyFuture(T &&value)
{
return makeReadyValueFuture(std::forward<T>(value));
@@ -1026,7 +1017,7 @@ static QFuture<std::decay_t<T>> makeReadyFuture(T &&value)
// uses makeReadyVoidFuture() and required QFuture<void> to be defined.
template<typename T>
-QT_DEPRECATED_VERSION_X(6, 10, "Use makeReadyRangeFuture() instead")
+QT_DEPRECATED_VERSION_X(6, 10, "Use makeReadyRangeFuture() instead.")
static QFuture<T> makeReadyFuture(const QList<T> &values)
{
return makeReadyRangeFuture(values);
@@ -1111,9 +1102,10 @@ void addCompletionHandlersImpl(const std::shared_ptr<ContextType> &context,
{
auto future = std::get<Index>(t);
using ResultType = typename ContextType::ValueType;
- future.then([context](const std::tuple_element_t<Index, std::tuple<Ts...>> &f) {
+ // Need context=context so that the compiler does not infer the captured variable's type as 'const'
+ future.then([context=context](const std::tuple_element_t<Index, std::tuple<Ts...>> &f) {
context->checkForCompletion(Index, ResultType { std::in_place_index<Index>, f });
- }).onCanceled([context, future]() {
+ }).onCanceled([context=context, future]() {
context->checkForCompletion(Index, ResultType { std::in_place_index<Index>, future });
});
@@ -1141,9 +1133,10 @@ QFuture<OutputSequence> whenAllImpl(InputIt first, InputIt last)
qsizetype idx = 0;
for (auto it = first; it != last; ++it, ++idx) {
- it->then([context, idx](const ValueType &f) {
+ // Need context=context so that the compiler does not infer the captured variable's type as 'const'
+ it->then([context=context, idx](const ValueType &f) {
context->checkForCompletion(idx, f);
- }).onCanceled([context, idx, f = *it] {
+ }).onCanceled([context=context, idx, f = *it] {
context->checkForCompletion(idx, f);
});
}
@@ -1181,9 +1174,10 @@ QFuture<QtFuture::WhenAnyResult<typename Future<ValueType>::type>> whenAnyImpl(I
qsizetype idx = 0;
for (auto it = first; it != last; ++it, ++idx) {
- it->then([context, idx](const ValueType &f) {
+ // Need context=context so that the compiler does not infer the captured variable's type as 'const'
+ it->then([context=context, idx](const ValueType &f) {
context->checkForCompletion(idx, QtFuture::WhenAnyResult { idx, f });
- }).onCanceled([context, idx, f = *it] {
+ }).onCanceled([context=context, idx, f = *it] {
context->checkForCompletion(idx, QtFuture::WhenAnyResult { idx, f });
});
}