summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/corelib/thread/qfuture_impl.h8
-rw-r--r--src/corelib/thread/qfutureinterface.cpp28
-rw-r--r--src/corelib/thread/qfutureinterface.h4
-rw-r--r--src/corelib/thread/qfutureinterface_p.h1
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