diff options
author | Dan Vrátil <dvratil@redhat.com> | 2015-04-03 18:17:12 +0200 |
---|---|---|
committer | Dan Vrátil <dvratil@redhat.com> | 2015-04-04 20:44:17 +0200 |
commit | 27bc3300d670d65b9c5332308605ef8263c3939c (patch) | |
tree | 038ced028bc2af9f600250feff845c9d4f936c54 /async | |
parent | 160255f96e46818b6df63b00f17f502df9ab0a79 (diff) | |
download | sink-27bc3300d670d65b9c5332308605ef8263c3939c.tar.gz sink-27bc3300d670d65b9c5332308605ef8263c3939c.zip |
Async: implement progress reporting through future
This is a simplified progress reporting, since it does not report progress
of ther overcall Job chain, but only of individual tasks, which makes it
only really useful on one-task Jobs.
TODO: propagate subjob progress to the Future user gets copy of
TODO: compound progress reporting (be able to report a progress of the overall
Job chain)
Diffstat (limited to 'async')
-rw-r--r-- | async/autotests/asynctest.cpp | 62 | ||||
-rw-r--r-- | async/src/async.h | 2 | ||||
-rw-r--r-- | async/src/future.cpp | 20 | ||||
-rw-r--r-- | async/src/future.h | 5 |
4 files changed, 88 insertions, 1 deletions
diff --git a/async/autotests/asynctest.cpp b/async/autotests/asynctest.cpp index 61ab8bc..7b8d430 100644 --- a/async/autotests/asynctest.cpp +++ b/async/autotests/asynctest.cpp | |||
@@ -60,6 +60,7 @@ private Q_SLOTS: | |||
60 | void testJoinedReduce(); | 60 | void testJoinedReduce(); |
61 | void testVoidReduce(); | 61 | void testVoidReduce(); |
62 | 62 | ||
63 | void testProgressReporting(); | ||
63 | void testErrorHandler(); | 64 | void testErrorHandler(); |
64 | 65 | ||
65 | void testChainingRunningJob(); | 66 | void testChainingRunningJob(); |
@@ -69,6 +70,7 @@ private Q_SLOTS: | |||
69 | void testLifetimeWithHandle(); | 70 | void testLifetimeWithHandle(); |
70 | 71 | ||
71 | void benchmarkSyncThenExecutor(); | 72 | void benchmarkSyncThenExecutor(); |
73 | void benchmarkAllTests(); | ||
72 | 74 | ||
73 | private: | 75 | private: |
74 | template<typename T> | 76 | template<typename T> |
@@ -471,6 +473,40 @@ void AsyncTest::testVoidReduce() | |||
471 | } | 473 | } |
472 | 474 | ||
473 | 475 | ||
476 | void AsyncTest::testProgressReporting() | ||
477 | { | ||
478 | static int progress; | ||
479 | progress = 0; | ||
480 | |||
481 | auto job = Async::start<void>( | ||
482 | [](Async::Future<void> &f) { | ||
483 | QTimer *timer = new QTimer(); | ||
484 | connect(timer, &QTimer::timeout, | ||
485 | [&f, timer]() { | ||
486 | f.setProgress(++progress); | ||
487 | if (progress == 100) { | ||
488 | timer->stop(); | ||
489 | timer->deleteLater(); | ||
490 | f.setFinished(); | ||
491 | } | ||
492 | }); | ||
493 | timer->start(1); | ||
494 | }); | ||
495 | |||
496 | int progressCheck = 0; | ||
497 | Async::FutureWatcher<void> watcher; | ||
498 | connect(&watcher, &Async::FutureWatcher<void>::futureProgress, | ||
499 | [&progressCheck](qreal progress) { | ||
500 | progressCheck++; | ||
501 | // FIXME: Don't use Q_ASSERT in unit tests | ||
502 | Q_ASSERT((int) progress == progressCheck); | ||
503 | }); | ||
504 | watcher.setFuture(job.exec()); | ||
505 | watcher.future().waitForFinished(); | ||
506 | |||
507 | QVERIFY(watcher.future().isFinished()); | ||
508 | QCOMPARE(progressCheck, 100); | ||
509 | } | ||
474 | 510 | ||
475 | void AsyncTest::testErrorHandler() | 511 | void AsyncTest::testErrorHandler() |
476 | { | 512 | { |
@@ -634,6 +670,32 @@ void AsyncTest::benchmarkSyncThenExecutor() | |||
634 | } | 670 | } |
635 | } | 671 | } |
636 | 672 | ||
673 | void AsyncTest::benchmarkAllTests() | ||
674 | { | ||
675 | QBENCHMARK { | ||
676 | testSyncPromises(); | ||
677 | testAsyncPromises(); | ||
678 | testAsyncPromises2(); | ||
679 | testNestedAsync(); | ||
680 | testStartValue(); | ||
681 | |||
682 | testAsyncThen(); | ||
683 | testSyncThen(); | ||
684 | testJoinedThen(); | ||
685 | testVoidThen(); | ||
686 | |||
687 | testAsyncEach(); | ||
688 | testSyncEach(); | ||
689 | testJoinedEach(); | ||
690 | testVoidEach(); | ||
691 | |||
692 | testAsyncReduce(); | ||
693 | testSyncReduce(); | ||
694 | testJoinedReduce(); | ||
695 | testVoidReduce(); | ||
696 | } | ||
697 | } | ||
698 | |||
637 | 699 | ||
638 | 700 | ||
639 | QTEST_MAIN(AsyncTest); | 701 | QTEST_MAIN(AsyncTest); |
diff --git a/async/src/async.h b/async/src/async.h index 6cb3825..c316639 100644 --- a/async/src/async.h +++ b/async/src/async.h | |||
@@ -56,7 +56,7 @@ | |||
56 | * valid until the task is complete. To abort a job it has to be killed through the future handle. | 56 | * valid until the task is complete. To abort a job it has to be killed through the future handle. |
57 | * TODO: Can we tie the lifetime of the executor to the last available future handle? | 57 | * TODO: Can we tie the lifetime of the executor to the last available future handle? |
58 | * | 58 | * |
59 | * TODO: Progress reporting through future | 59 | * TODO: Composed progress reporting |
60 | * TODO: Possibility to abort a job through future (perhaps optional?) | 60 | * TODO: Possibility to abort a job through future (perhaps optional?) |
61 | * TODO: Support for timeout, specified during exec call, after which the error handler gets called with a defined errorCode. | 61 | * TODO: Support for timeout, specified during exec call, after which the error handler gets called with a defined errorCode. |
62 | */ | 62 | */ |
diff --git a/async/src/future.cpp b/async/src/future.cpp index 970060b..4f3cd80 100644 --- a/async/src/future.cpp +++ b/async/src/future.cpp | |||
@@ -102,6 +102,21 @@ QString FutureBase::errorMessage() const | |||
102 | return d->errorMessage; | 102 | return d->errorMessage; |
103 | } | 103 | } |
104 | 104 | ||
105 | void FutureBase::setProgress(int processed, int total) | ||
106 | { | ||
107 | setProgress((qreal) processed / total); | ||
108 | } | ||
109 | |||
110 | void FutureBase::setProgress(qreal progress) | ||
111 | { | ||
112 | for (auto watcher : d->watchers) { | ||
113 | if (watcher) { | ||
114 | watcher->futureProgressCallback(progress); | ||
115 | } | ||
116 | } | ||
117 | } | ||
118 | |||
119 | |||
105 | 120 | ||
106 | void FutureBase::addWatcher(FutureWatcherBase* watcher) | 121 | void FutureBase::addWatcher(FutureWatcherBase* watcher) |
107 | { | 122 | { |
@@ -128,6 +143,11 @@ void FutureWatcherBase::futureReadyCallback() | |||
128 | Q_EMIT futureReady(); | 143 | Q_EMIT futureReady(); |
129 | } | 144 | } |
130 | 145 | ||
146 | void FutureWatcherBase::futureProgressCallback(qreal progress) | ||
147 | { | ||
148 | Q_EMIT futureProgress(progress); | ||
149 | } | ||
150 | |||
131 | void FutureWatcherBase::setFutureImpl(const FutureBase &future) | 151 | void FutureWatcherBase::setFutureImpl(const FutureBase &future) |
132 | { | 152 | { |
133 | d->future = future; | 153 | d->future = future; |
diff --git a/async/src/future.h b/async/src/future.h index bc18f00..32c1015 100644 --- a/async/src/future.h +++ b/async/src/future.h | |||
@@ -54,6 +54,9 @@ public: | |||
54 | int errorCode() const; | 54 | int errorCode() const; |
55 | QString errorMessage() const; | 55 | QString errorMessage() const; |
56 | 56 | ||
57 | void setProgress(qreal progress); | ||
58 | void setProgress(int processed, int total); | ||
59 | |||
57 | protected: | 60 | protected: |
58 | class PrivateBase : public QSharedData | 61 | class PrivateBase : public QSharedData |
59 | { | 62 | { |
@@ -197,12 +200,14 @@ class FutureWatcherBase : public QObject | |||
197 | 200 | ||
198 | Q_SIGNALS: | 201 | Q_SIGNALS: |
199 | void futureReady(); | 202 | void futureReady(); |
203 | void futureProgress(qreal progress); | ||
200 | 204 | ||
201 | protected: | 205 | protected: |
202 | FutureWatcherBase(QObject *parent = nullptr); | 206 | FutureWatcherBase(QObject *parent = nullptr); |
203 | virtual ~FutureWatcherBase(); | 207 | virtual ~FutureWatcherBase(); |
204 | 208 | ||
205 | void futureReadyCallback(); | 209 | void futureReadyCallback(); |
210 | void futureProgressCallback(qreal progress); | ||
206 | 211 | ||
207 | void setFutureImpl(const Async::FutureBase &future); | 212 | void setFutureImpl(const Async::FutureBase &future); |
208 | 213 | ||