diff options
Diffstat (limited to 'src/corelib/thread/qfuture_impl.h')
-rw-r--r-- | src/corelib/thread/qfuture_impl.h | 80 |
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 }); }); } |