From 94729eef71570e0b792a9afb95eeab7fd1eec56b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dan=20Vr=C3=A1til?= Date: Wed, 1 Apr 2015 13:24:41 +0200 Subject: Async: have the top executor reference itself during execution The only reference to the top executor (the last in chain) is held by the Job. If the Job goes out of scope after it's executed, the top Executor is deleted (which in turn deletes the entire Executor chain). By having the top Executor holding reference to itself during execution we ensure that the Executor chain is not deleted until the job is finished, even when the parent Job object is deleted in the meanwhile. --- async/src/async.h | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) (limited to 'async/src') diff --git a/async/src/async.h b/async/src/async.h index 57879a7..2741341 100644 --- a/async/src/async.h +++ b/async/src/async.h @@ -114,6 +114,7 @@ public: protected: ExecutorBase(const ExecutorBasePtr &parent); + ExecutorBasePtr mSelf; ExecutorBasePtr mPrev; FutureBase *mResult; bool mIsRunning; @@ -429,6 +430,11 @@ public: Async::Future exec() { + // Have the top executor hold reference to itself during the execution. + // This ensures that even if the Job goes out of scope, the full Executor + // chain will not be destroyed. + // The executor will remove the self-reference once it's Future is finished. + mExecutor->mSelf = mExecutor; mExecutor->exec(); return result(); } @@ -471,7 +477,7 @@ private: [watcher, &future]() { Async::detail::copyFutureValue(watcher->future(), future); future.setFinished(); - watcher->deleteLater(); + delete watcher; }); watcher->setFuture(job.exec(in ...)); }; @@ -569,10 +575,12 @@ void Executor::exec() mResult = new Async::Future(); auto fw = new Async::FutureWatcher(); QObject::connect(fw, &Async::FutureWatcher::futureReady, - [&]() { + [fw, this]() { mIsFinished = true; - fw->deleteLater(); + mSelf.clear(); + delete fw; }); + fw->setFuture(*static_cast*>(mResult)); if (!mPrevFuture || mPrevFuture->isFinished()) { if (mPrevFuture && mPrevFuture->errorCode() != 0) { @@ -593,7 +601,7 @@ void Executor::exec() [futureWatcher, this]() { auto prevFuture = futureWatcher->future(); assert(prevFuture.isFinished()); - futureWatcher->deleteLater(); + delete futureWatcher; if (prevFuture.errorCode() != 0) { if (mErrorFunc) { mErrorFunc(prevFuture.errorCode(), prevFuture.errorMessage()); -- cgit v1.2.3