diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/corelib/thread/qfuture_impl.h | 8 | ||||
-rw-r--r-- | src/corelib/thread/qfutureinterface.cpp | 28 | ||||
-rw-r--r-- | src/corelib/thread/qfutureinterface.h | 4 | ||||
-rw-r--r-- | src/corelib/thread/qfutureinterface_p.h | 1 |
4 files changed, 37 insertions, 4 deletions
diff --git a/src/corelib/thread/qfuture_impl.h b/src/corelib/thread/qfuture_impl.h index 511caafdf7..d7132caa7b 100644 --- a/src/corelib/thread/qfuture_impl.h +++ b/src/corelib/thread/qfuture_impl.h @@ -425,7 +425,7 @@ bool Continuation<Function, ResultType, ParentResultType>::execute() { Q_ASSERT(parentFuture.isFinished()); - if (parentFuture.isCanceled()) { + if (parentFuture.d.isChainCanceled()) { #ifndef QT_NO_EXCEPTIONS if (parentFuture.d.hasException()) { // If the continuation doesn't take a QFuture argument, propagate the exception @@ -498,7 +498,7 @@ void Continuation<Function, ResultType, ParentResultType>::create(F &&func, } }; - f->d.setContinuation(std::move(continuation)); + f->d.setContinuation(std::move(continuation), p.d); } template<typename Function, typename ResultType, typename ParentResultType> @@ -527,7 +527,7 @@ void Continuation<Function, ResultType, ParentResultType>::create(F &&func, } }; - f->d.setContinuation(std::move(continuation)); + f->d.setContinuation(std::move(continuation), p.d); } template<typename Function, typename ResultType, typename ParentResultType> @@ -550,7 +550,7 @@ void Continuation<Function, ResultType, ParentResultType>::create(F &&func, }); }; - f->d.setContinuation(std::move(continuation)); + f->d.setContinuation(std::move(continuation), p.d); } template<typename Function, typename ResultType, typename ParentResultType> diff --git a/src/corelib/thread/qfutureinterface.cpp b/src/corelib/thread/qfutureinterface.cpp index e640114bb0..7512d6174a 100644 --- a/src/corelib/thread/qfutureinterface.cpp +++ b/src/corelib/thread/qfutureinterface.cpp @@ -835,7 +835,17 @@ void QFutureInterfaceBasePrivate::setState(QFutureInterfaceBase::State newState) void QFutureInterfaceBase::setContinuation(std::function<void(const QFutureInterfaceBase &)> func) { + setContinuation(func, nullptr); +} + +void QFutureInterfaceBase::setContinuation(std::function<void(const QFutureInterfaceBase &)> func, + QFutureInterfaceBasePrivate *continuationFutureData) +{ QMutexLocker lock(&d->continuationMutex); + + if (continuationFutureData) + continuationFutureData->parentData = d; + // If the state is ready, run continuation immediately, // otherwise save it for later. if (isFinished()) { @@ -855,6 +865,24 @@ void QFutureInterfaceBase::runContinuation() const } } +bool QFutureInterfaceBase::isChainCanceled() const +{ + if (isCanceled()) + return true; + + auto parent = d->parentData; + while (parent) { + // If the future is in Canceled state because it had an exception, we want to + // continue checking the chain of parents for cancellation, otherwise if the exception + // is handeled inside the chain, it won't be interrupted even though cancellation has + // been requested. + if ((parent->state.loadRelaxed() & Canceled) && !parent->hasException) + return true; + parent = parent->parentData; + } + return false; +} + void QFutureInterfaceBase::setLaunchAsync(bool value) { d->launchAsync = value; diff --git a/src/corelib/thread/qfutureinterface.h b/src/corelib/thread/qfutureinterface.h index e813031d59..3130c91420 100644 --- a/src/corelib/thread/qfutureinterface.h +++ b/src/corelib/thread/qfutureinterface.h @@ -182,6 +182,8 @@ public: template<typename T> static QFutureInterfaceBase get(const QFuture<T> &future); // implemented in qfuture.h + bool isChainCanceled() const; + protected: // ### Qt 7: remove const from refT/derefT bool refT() const noexcept; @@ -212,6 +214,8 @@ private: protected: void setContinuation(std::function<void(const QFutureInterfaceBase &)> func); + void setContinuation(std::function<void(const QFutureInterfaceBase &)> func, + QFutureInterfaceBasePrivate *continuationFutureData); void runContinuation() const; void setLaunchAsync(bool value); diff --git a/src/corelib/thread/qfutureinterface_p.h b/src/corelib/thread/qfutureinterface_p.h index c92f8e2230..fd7f34826d 100644 --- a/src/corelib/thread/qfutureinterface_p.h +++ b/src/corelib/thread/qfutureinterface_p.h @@ -190,6 +190,7 @@ public: QThreadPool *m_pool = nullptr; // Wrapper for continuation std::function<void(const QFutureInterfaceBase &)> continuation; + QFutureInterfaceBasePrivate *parentData = nullptr; RefCount refCount = 1; QAtomicInt state; // reads and writes can happen unprotected, both must be atomic |