summaryrefslogtreecommitdiffstats
path: root/async/src
diff options
context:
space:
mode:
authorDan Vrátil <dvratil@redhat.com>2015-04-01 13:24:41 +0200
committerDan Vrátil <dvratil@redhat.com>2015-04-01 13:24:54 +0200
commit94729eef71570e0b792a9afb95eeab7fd1eec56b (patch)
tree1c09d92fc29764f1bf7322d13487caabb19002be /async/src
parentfb4c36e3daded17746a0bcd7c245b8cea9782c1a (diff)
downloadsink-94729eef71570e0b792a9afb95eeab7fd1eec56b.tar.gz
sink-94729eef71570e0b792a9afb95eeab7fd1eec56b.zip
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.
Diffstat (limited to 'async/src')
-rw-r--r--async/src/async.h16
1 files changed, 12 insertions, 4 deletions
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:
114protected: 114protected:
115 ExecutorBase(const ExecutorBasePtr &parent); 115 ExecutorBase(const ExecutorBasePtr &parent);
116 116
117 ExecutorBasePtr mSelf;
117 ExecutorBasePtr mPrev; 118 ExecutorBasePtr mPrev;
118 FutureBase *mResult; 119 FutureBase *mResult;
119 bool mIsRunning; 120 bool mIsRunning;
@@ -429,6 +430,11 @@ public:
429 430
430 Async::Future<Out> exec() 431 Async::Future<Out> exec()
431 { 432 {
433 // Have the top executor hold reference to itself during the execution.
434 // This ensures that even if the Job goes out of scope, the full Executor
435 // chain will not be destroyed.
436 // The executor will remove the self-reference once it's Future is finished.
437 mExecutor->mSelf = mExecutor;
432 mExecutor->exec(); 438 mExecutor->exec();
433 return result(); 439 return result();
434 } 440 }
@@ -471,7 +477,7 @@ private:
471 [watcher, &future]() { 477 [watcher, &future]() {
472 Async::detail::copyFutureValue(watcher->future(), future); 478 Async::detail::copyFutureValue(watcher->future(), future);
473 future.setFinished(); 479 future.setFinished();
474 watcher->deleteLater(); 480 delete watcher;
475 }); 481 });
476 watcher->setFuture(job.exec(in ...)); 482 watcher->setFuture(job.exec(in ...));
477 }; 483 };
@@ -569,10 +575,12 @@ void Executor<PrevOut, Out, In ...>::exec()
569 mResult = new Async::Future<Out>(); 575 mResult = new Async::Future<Out>();
570 auto fw = new Async::FutureWatcher<Out>(); 576 auto fw = new Async::FutureWatcher<Out>();
571 QObject::connect(fw, &Async::FutureWatcher<Out>::futureReady, 577 QObject::connect(fw, &Async::FutureWatcher<Out>::futureReady,
572 [&]() { 578 [fw, this]() {
573 mIsFinished = true; 579 mIsFinished = true;
574 fw->deleteLater(); 580 mSelf.clear();
581 delete fw;
575 }); 582 });
583 fw->setFuture(*static_cast<Async::Future<Out>*>(mResult));
576 584
577 if (!mPrevFuture || mPrevFuture->isFinished()) { 585 if (!mPrevFuture || mPrevFuture->isFinished()) {
578 if (mPrevFuture && mPrevFuture->errorCode() != 0) { 586 if (mPrevFuture && mPrevFuture->errorCode() != 0) {
@@ -593,7 +601,7 @@ void Executor<PrevOut, Out, In ...>::exec()
593 [futureWatcher, this]() { 601 [futureWatcher, this]() {
594 auto prevFuture = futureWatcher->future(); 602 auto prevFuture = futureWatcher->future();
595 assert(prevFuture.isFinished()); 603 assert(prevFuture.isFinished());
596 futureWatcher->deleteLater(); 604 delete futureWatcher;
597 if (prevFuture.errorCode() != 0) { 605 if (prevFuture.errorCode() != 0) {
598 if (mErrorFunc) { 606 if (mErrorFunc) {
599 mErrorFunc(prevFuture.errorCode(), prevFuture.errorMessage()); 607 mErrorFunc(prevFuture.errorCode(), prevFuture.errorMessage());