diff options
Diffstat (limited to 'async')
-rw-r--r-- | async/autotests/asynctest.cpp | 72 | ||||
-rw-r--r-- | async/src/async.cpp | 2 | ||||
-rw-r--r-- | async/src/async.h | 21 |
3 files changed, 94 insertions, 1 deletions
diff --git a/async/autotests/asynctest.cpp b/async/autotests/asynctest.cpp index 73026bb..7437608 100644 --- a/async/autotests/asynctest.cpp +++ b/async/autotests/asynctest.cpp | |||
@@ -59,6 +59,10 @@ private Q_SLOTS: | |||
59 | 59 | ||
60 | void testErrorHandler(); | 60 | void testErrorHandler(); |
61 | 61 | ||
62 | |||
63 | void testChainingRunningJob(); | ||
64 | void testChainingFinishedJob(); | ||
65 | |||
62 | void benchmarkSyncThenExecutor(); | 66 | void benchmarkSyncThenExecutor(); |
63 | 67 | ||
64 | private: | 68 | private: |
@@ -399,6 +403,74 @@ void AsyncTest::testErrorHandler() | |||
399 | 403 | ||
400 | 404 | ||
401 | 405 | ||
406 | void AsyncTest::testChainingRunningJob() | ||
407 | { | ||
408 | int check = 0; | ||
409 | |||
410 | auto job = Async::start<int>( | ||
411 | [&check](Async::Future<int> &future) { | ||
412 | QTimer *timer = new QTimer(); | ||
413 | QObject::connect(timer, &QTimer::timeout, | ||
414 | [&future, &check]() { | ||
415 | ++check; | ||
416 | future.setValue(42); | ||
417 | future.setFinished(); | ||
418 | }); | ||
419 | QObject::connect(timer, &QTimer::timeout, | ||
420 | timer, &QObject::deleteLater); | ||
421 | timer->setSingleShot(true); | ||
422 | timer->start(500); | ||
423 | }); | ||
424 | |||
425 | auto future1 = job.exec(); | ||
426 | QTest::qWait(200); | ||
427 | |||
428 | auto job2 = job.then<int, int>( | ||
429 | [&check](int in) -> int { | ||
430 | ++check; | ||
431 | return in * 2; | ||
432 | }); | ||
433 | |||
434 | auto future2 = job2.exec(); | ||
435 | QVERIFY(!future1.isFinished()); | ||
436 | future2.waitForFinished(); | ||
437 | |||
438 | QCOMPARE(check, 2); | ||
439 | QVERIFY(future1.isFinished()); | ||
440 | QVERIFY(future2.isFinished()); | ||
441 | QCOMPARE(future1.value(), 42); | ||
442 | QCOMPARE(future2.value(), 84); | ||
443 | } | ||
444 | |||
445 | void AsyncTest::testChainingFinishedJob() | ||
446 | { | ||
447 | int check = 0; | ||
448 | |||
449 | auto job = Async::start<int>( | ||
450 | [&check]() -> int { | ||
451 | ++check; | ||
452 | return 42; | ||
453 | }); | ||
454 | |||
455 | auto future1 = job.exec(); | ||
456 | QVERIFY(future1.isFinished()); | ||
457 | |||
458 | auto job2 = job.then<int, int>( | ||
459 | [&check](int in) -> int { | ||
460 | ++check; | ||
461 | return in * 2; | ||
462 | }); | ||
463 | |||
464 | auto future2 = job2.exec(); | ||
465 | QVERIFY(future2.isFinished()); | ||
466 | |||
467 | QCOMPARE(check, 2); | ||
468 | QCOMPARE(future1.value(), 42); | ||
469 | QCOMPARE(future2.value(), 84); | ||
470 | } | ||
471 | |||
472 | |||
473 | |||
402 | 474 | ||
403 | 475 | ||
404 | void AsyncTest::benchmarkSyncThenExecutor() | 476 | void AsyncTest::benchmarkSyncThenExecutor() |
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; | |||
27 | Private::ExecutorBase::ExecutorBase(const ExecutorBasePtr &parent) | 27 | Private::ExecutorBase::ExecutorBase(const ExecutorBasePtr &parent) |
28 | : mPrev(parent) | 28 | : mPrev(parent) |
29 | , mResult(0) | 29 | , mResult(0) |
30 | , mIsRunning(false) | ||
31 | , mIsFinished(false) | ||
30 | { | 32 | { |
31 | } | 33 | } |
32 | 34 | ||
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 | ||
95 | template<typename PrevOut, typename Out, typename ... In> | 97 | template<typename PrevOut, typename Out, typename ... In> |
@@ -470,19 +472,35 @@ Future<PrevOut>* Executor<PrevOut, Out, In ...>::chainup() | |||
470 | template<typename PrevOut, typename Out, typename ... In> | 472 | template<typename PrevOut, typename Out, typename ... In> |
471 | void Executor<PrevOut, Out, In ...>::exec() | 473 | void 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 | ||