From 27bc3300d670d65b9c5332308605ef8263c3939c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dan=20Vr=C3=A1til?= Date: Fri, 3 Apr 2015 18:17:12 +0200 Subject: 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) --- async/autotests/asynctest.cpp | 62 +++++++++++++++++++++++++++++++++++++++++++ async/src/async.h | 2 +- async/src/future.cpp | 20 ++++++++++++++ async/src/future.h | 5 ++++ 4 files changed, 88 insertions(+), 1 deletion(-) 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: void testJoinedReduce(); void testVoidReduce(); + void testProgressReporting(); void testErrorHandler(); void testChainingRunningJob(); @@ -69,6 +70,7 @@ private Q_SLOTS: void testLifetimeWithHandle(); void benchmarkSyncThenExecutor(); + void benchmarkAllTests(); private: template @@ -471,6 +473,40 @@ void AsyncTest::testVoidReduce() } +void AsyncTest::testProgressReporting() +{ + static int progress; + progress = 0; + + auto job = Async::start( + [](Async::Future &f) { + QTimer *timer = new QTimer(); + connect(timer, &QTimer::timeout, + [&f, timer]() { + f.setProgress(++progress); + if (progress == 100) { + timer->stop(); + timer->deleteLater(); + f.setFinished(); + } + }); + timer->start(1); + }); + + int progressCheck = 0; + Async::FutureWatcher watcher; + connect(&watcher, &Async::FutureWatcher::futureProgress, + [&progressCheck](qreal progress) { + progressCheck++; + // FIXME: Don't use Q_ASSERT in unit tests + Q_ASSERT((int) progress == progressCheck); + }); + watcher.setFuture(job.exec()); + watcher.future().waitForFinished(); + + QVERIFY(watcher.future().isFinished()); + QCOMPARE(progressCheck, 100); +} void AsyncTest::testErrorHandler() { @@ -634,6 +670,32 @@ void AsyncTest::benchmarkSyncThenExecutor() } } +void AsyncTest::benchmarkAllTests() +{ + QBENCHMARK { + testSyncPromises(); + testAsyncPromises(); + testAsyncPromises2(); + testNestedAsync(); + testStartValue(); + + testAsyncThen(); + testSyncThen(); + testJoinedThen(); + testVoidThen(); + + testAsyncEach(); + testSyncEach(); + testJoinedEach(); + testVoidEach(); + + testAsyncReduce(); + testSyncReduce(); + testJoinedReduce(); + testVoidReduce(); + } +} + 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 @@ * valid until the task is complete. To abort a job it has to be killed through the future handle. * TODO: Can we tie the lifetime of the executor to the last available future handle? * - * TODO: Progress reporting through future + * TODO: Composed progress reporting * TODO: Possibility to abort a job through future (perhaps optional?) * TODO: Support for timeout, specified during exec call, after which the error handler gets called with a defined errorCode. */ 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 return d->errorMessage; } +void FutureBase::setProgress(int processed, int total) +{ + setProgress((qreal) processed / total); +} + +void FutureBase::setProgress(qreal progress) +{ + for (auto watcher : d->watchers) { + if (watcher) { + watcher->futureProgressCallback(progress); + } + } +} + + void FutureBase::addWatcher(FutureWatcherBase* watcher) { @@ -128,6 +143,11 @@ void FutureWatcherBase::futureReadyCallback() Q_EMIT futureReady(); } +void FutureWatcherBase::futureProgressCallback(qreal progress) +{ + Q_EMIT futureProgress(progress); +} + void FutureWatcherBase::setFutureImpl(const FutureBase &future) { 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: int errorCode() const; QString errorMessage() const; + void setProgress(qreal progress); + void setProgress(int processed, int total); + protected: class PrivateBase : public QSharedData { @@ -197,12 +200,14 @@ class FutureWatcherBase : public QObject Q_SIGNALS: void futureReady(); + void futureProgress(qreal progress); protected: FutureWatcherBase(QObject *parent = nullptr); virtual ~FutureWatcherBase(); void futureReadyCallback(); + void futureProgressCallback(qreal progress); void setFutureImpl(const Async::FutureBase &future); -- cgit v1.2.3