summaryrefslogtreecommitdiffstats
path: root/async/src/async.h
diff options
context:
space:
mode:
authorDan Vrátil <dvratil@redhat.com>2015-02-21 12:11:42 +0100
committerDan Vrátil <dvratil@redhat.com>2015-02-21 12:11:44 +0100
commit3b8ebe6d4235f5ba12bc9c9854a6dd28cbff06b5 (patch)
tree4e2a987e6c62523994965789387cace578e4c8d8 /async/src/async.h
parent76ec0cfe075e3af758657f9aecab7d7ce7e8d387 (diff)
downloadsink-3b8ebe6d4235f5ba12bc9c9854a6dd28cbff06b5.tar.gz
sink-3b8ebe6d4235f5ba12bc9c9854a6dd28cbff06b5.zip
Async: allow appending Jobs to already running or finished Jobs
When user gets a Job (from a method call for instance), which is already running or might have even finished already, they can still append a new Job to the chain and re-execute it. The Job will internally chain up to the last finished Job, use it's result and continue from the next Job in the chain. If a Job in the chain is still running, it will wait for it to finish and pass the result to the next Job in the chain.
Diffstat (limited to 'async/src/async.h')
-rw-r--r--async/src/async.h21
1 files changed, 20 insertions, 1 deletions
diff --git a/async/src/async.h b/async/src/async.h
index d21caf8..8296fbc 100644
--- a/async/src/async.h
+++ b/async/src/async.h
@@ -90,6 +90,8 @@ protected:
90 90
91 ExecutorBasePtr mPrev; 91 ExecutorBasePtr mPrev;
92 FutureBase *mResult; 92 FutureBase *mResult;
93 bool mIsRunning;
94 bool mIsFinished;
93}; 95};
94 96
95template<typename PrevOut, typename Out, typename ... In> 97template<typename PrevOut, typename Out, typename ... In>
@@ -470,19 +472,35 @@ Future<PrevOut>* Executor<PrevOut, Out, In ...>::chainup()
470template<typename PrevOut, typename Out, typename ... In> 472template<typename PrevOut, typename Out, typename ... In>
471void Executor<PrevOut, Out, In ...>::exec() 473void Executor<PrevOut, Out, In ...>::exec()
472{ 474{
473 mPrevFuture = chainup(); 475 // Don't chain up to job that already is running (or is finished)
476 if (mPrev && !mPrev->mIsRunning & !mPrev->mIsFinished) {
477 mPrevFuture = chainup();
478 } else if (mPrev && !mPrevFuture) {
479 // If previous job is running or finished, just get it's future
480 mPrevFuture = static_cast<Async::Future<PrevOut>*>(mPrev->result());
481 }
482
474 // Initialize our future 483 // Initialize our future
475 mResult = new Async::Future<Out>(); 484 mResult = new Async::Future<Out>();
485 auto fw = new Async::FutureWatcher<Out>();
486 QObject::connect(fw, &Async::FutureWatcher<Out>::futureReady,
487 [&]() {
488 mIsFinished = true;
489 fw->deleteLater();
490 });
491
476 if (!mPrevFuture || mPrevFuture->isFinished()) { 492 if (!mPrevFuture || mPrevFuture->isFinished()) {
477 if (mPrevFuture && mPrevFuture->errorCode() != 0) { 493 if (mPrevFuture && mPrevFuture->errorCode() != 0) {
478 if (mErrorFunc) { 494 if (mErrorFunc) {
479 mErrorFunc(mPrevFuture->errorCode(), mPrevFuture->errorMessage()); 495 mErrorFunc(mPrevFuture->errorCode(), mPrevFuture->errorMessage());
480 mResult->setFinished(); 496 mResult->setFinished();
497 mIsFinished = true;
481 return; 498 return;
482 } else { 499 } else {
483 // Propagate the error to next caller 500 // Propagate the error to next caller
484 } 501 }
485 } 502 }
503 mIsRunning = true;
486 previousFutureReady(); 504 previousFutureReady();
487 } else { 505 } else {
488 auto futureWatcher = new Async::FutureWatcher<PrevOut>(); 506 auto futureWatcher = new Async::FutureWatcher<PrevOut>();
@@ -500,6 +518,7 @@ void Executor<PrevOut, Out, In ...>::exec()
500 // Propagate the error to next caller 518 // Propagate the error to next caller
501 } 519 }
502 } 520 }
521 mIsRunning = true;
503 previousFutureReady(); 522 previousFutureReady();
504 }); 523 });
505 524