From 3b8ebe6d4235f5ba12bc9c9854a6dd28cbff06b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dan=20Vr=C3=A1til?= Date: Sat, 21 Feb 2015 12:11:42 +0100 Subject: 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. --- async/src/async.cpp | 2 ++ async/src/async.h | 21 ++++++++++++++++++++- 2 files changed, 22 insertions(+), 1 deletion(-) (limited to 'async/src') diff --git a/async/src/async.cpp b/async/src/async.cpp index c9fedc7..6eefd1b 100644 --- a/async/src/async.cpp +++ b/async/src/async.cpp @@ -27,6 +27,8 @@ using namespace Async; Private::ExecutorBase::ExecutorBase(const ExecutorBasePtr &parent) : mPrev(parent) , mResult(0) + , mIsRunning(false) + , mIsFinished(false) { } 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: ExecutorBasePtr mPrev; FutureBase *mResult; + bool mIsRunning; + bool mIsFinished; }; template @@ -470,19 +472,35 @@ Future* Executor::chainup() template void Executor::exec() { - mPrevFuture = chainup(); + // Don't chain up to job that already is running (or is finished) + if (mPrev && !mPrev->mIsRunning & !mPrev->mIsFinished) { + mPrevFuture = chainup(); + } else if (mPrev && !mPrevFuture) { + // If previous job is running or finished, just get it's future + mPrevFuture = static_cast*>(mPrev->result()); + } + // Initialize our future mResult = new Async::Future(); + auto fw = new Async::FutureWatcher(); + QObject::connect(fw, &Async::FutureWatcher::futureReady, + [&]() { + mIsFinished = true; + fw->deleteLater(); + }); + if (!mPrevFuture || mPrevFuture->isFinished()) { if (mPrevFuture && mPrevFuture->errorCode() != 0) { if (mErrorFunc) { mErrorFunc(mPrevFuture->errorCode(), mPrevFuture->errorMessage()); mResult->setFinished(); + mIsFinished = true; return; } else { // Propagate the error to next caller } } + mIsRunning = true; previousFutureReady(); } else { auto futureWatcher = new Async::FutureWatcher(); @@ -500,6 +518,7 @@ void Executor::exec() // Propagate the error to next caller } } + mIsRunning = true; previousFutureReady(); }); -- cgit v1.2.3