TaskTree: Reuse withTimeout()

Add static runBlocking() overloads.
Replace int timeout arg with std::chrono::milliseconds.

Change-Id: Id10a010f05eda8452cd7e4cd9ee46216087fc70e
Reviewed-by: <github-actions-qt-creator@cristianadam.eu>
Reviewed-by: Marcus Tillmanns <marcus.tillmanns@qt.io>
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
This commit is contained in:
Jarek Kobus
2023-05-29 01:10:39 +02:00
parent 6f8e5c409f
commit 3ee32c1a3b
7 changed files with 40 additions and 33 deletions

View File

@@ -1791,9 +1791,16 @@ bool TaskTree::isRunning() const
return d->m_root && d->m_root->isRunning(); return d->m_root && d->m_root->isRunning();
} }
bool TaskTree::runBlocking(const QFuture<void> &future, int timeoutMs) bool TaskTree::runBlocking()
{ {
if (isRunning() || future.isCanceled()) QPromise<void> dummy;
dummy.start();
return runBlocking(dummy.future());
}
bool TaskTree::runBlocking(const QFuture<void> &future)
{
if (future.isCanceled())
return false; return false;
bool ok = false; bool ok = false;
@@ -1812,17 +1819,7 @@ bool TaskTree::runBlocking(const QFuture<void> &future, int timeoutMs)
connect(this, &TaskTree::done, &loop, [finalize] { finalize(true); }); connect(this, &TaskTree::done, &loop, [finalize] { finalize(true); });
connect(this, &TaskTree::errorOccurred, &loop, [finalize] { finalize(false); }); connect(this, &TaskTree::errorOccurred, &loop, [finalize] { finalize(false); });
start(); QTimer::singleShot(0, this, &TaskTree::start);
if (!isRunning())
return ok;
QTimer timer;
if (timeoutMs) {
timer.setSingleShot(true);
timer.setInterval(timeoutMs);
connect(&timer, &QTimer::timeout, this, &TaskTree::stop);
timer.start();
}
loop.exec(QEventLoop::ExcludeUserInputEvents); loop.exec(QEventLoop::ExcludeUserInputEvents);
if (!ok) { if (!ok) {
@@ -1832,11 +1829,19 @@ bool TaskTree::runBlocking(const QFuture<void> &future, int timeoutMs)
return ok; return ok;
} }
bool TaskTree::runBlocking(int timeoutMs) bool TaskTree::runBlocking(const Group &recipe, milliseconds timeout)
{ {
QPromise<void> dummy; QPromise<void> dummy;
dummy.start(); dummy.start();
return runBlocking(dummy.future(), timeoutMs); return TaskTree::runBlocking(recipe, dummy.future(), timeout);
}
bool TaskTree::runBlocking(const Group &recipe, const QFuture<void> &future, milliseconds timeout)
{
const Group root = timeout == milliseconds::max() ? recipe
: Group { recipe.withTimeout(timeout) };
TaskTree taskTree(root);
return taskTree.runBlocking(future);
} }
int TaskTree::taskCount() const int TaskTree::taskCount() const

View File

@@ -390,8 +390,12 @@ public:
// Helper methods. They execute a local event loop with ExcludeUserInputEvents. // Helper methods. They execute a local event loop with ExcludeUserInputEvents.
// The passed future is used for listening to the cancel event. // The passed future is used for listening to the cancel event.
// Don't use it in main thread. To be used in non-main threads or in auto tests. // Don't use it in main thread. To be used in non-main threads or in auto tests.
bool runBlocking(const QFuture<void> &future, int timeoutMs = 0); bool runBlocking();
bool runBlocking(int timeoutMs = 0); bool runBlocking(const QFuture<void> &future);
static bool runBlocking(const Group &recipe,
std::chrono::milliseconds timeout = std::chrono::milliseconds::max());
static bool runBlocking(const Group &recipe, const QFuture<void> &future,
std::chrono::milliseconds timeout = std::chrono::milliseconds::max());
int taskCount() const; int taskCount() const;
int progressMaximum() const { return taskCount(); } int progressMaximum() const { return taskCount(); }

View File

@@ -375,8 +375,7 @@ static void transfer(QPromise<void> &promise, const FilePath &source, const File
if (promise.isCanceled()) if (promise.isCanceled())
return; return;
TaskTree taskTree(transferTask(source, destination)); if (!TaskTree::runBlocking(transferTask(source, destination), promise.future()))
if (!taskTree.runBlocking(promise.future()))
promise.future().cancel(); promise.future().cancel();
} }

View File

@@ -503,8 +503,8 @@ void FileSystemAccessTest::testFileStreamer()
} }
}; };
TaskTree taskTree(root); using namespace std::chrono_literals;
QVERIFY(taskTree.runBlocking(10000)); QVERIFY(TaskTree::runBlocking(root, 10000ms));
QVERIFY(localData); QVERIFY(localData);
QCOMPARE(*localData, data); QCOMPARE(*localData, data);

View File

@@ -2202,15 +2202,15 @@ void tst_Tasking::testTree()
{ {
QFETCH(TestData, testData); QFETCH(TestData, testData);
TaskTree taskTree(testData.root); TaskTree taskTree({testData.root.withTimeout(1000ms)});
QCOMPARE(taskTree.taskCount(), testData.taskCount); QCOMPARE(taskTree.taskCount() - 1, testData.taskCount); // -1 for the timeout task above
Log actualLog; Log actualLog;
const auto collectLog = [&actualLog](CustomStorage *storage) { actualLog = storage->m_log; }; const auto collectLog = [&actualLog](CustomStorage *storage) { actualLog = storage->m_log; };
taskTree.onStorageDone(testData.storage, collectLog); taskTree.onStorageDone(testData.storage, collectLog);
const OnDone result = taskTree.runBlocking(2000) ? OnDone::Success : OnDone::Failure; const OnDone result = taskTree.runBlocking() ? OnDone::Success : OnDone::Failure;
QCOMPARE(taskTree.isRunning(), false); QCOMPARE(taskTree.isRunning(), false);
QCOMPARE(taskTree.progressValue(), testData.taskCount); QCOMPARE(taskTree.progressValue(), taskTree.progressMaximum());
QCOMPARE(actualLog, testData.expectedLog); QCOMPARE(actualLog, testData.expectedLog);
QCOMPARE(CustomStorage::instanceCount(), 0); QCOMPARE(CustomStorage::instanceCount(), 0);

View File

@@ -8,6 +8,8 @@
using namespace Utils; using namespace Utils;
using namespace std::chrono_literals;
class tst_Async : public QObject class tst_Async : public QObject
{ {
Q_OBJECT Q_OBJECT
@@ -438,8 +440,8 @@ void tst_Async::taskTree()
AsyncTask<int>(setupIntAsync, handleIntAsync), AsyncTask<int>(setupIntAsync, handleIntAsync),
}; };
TaskTree tree(root);
QVERIFY(tree.runBlocking(1000)); QVERIFY(TaskTree::runBlocking(root, 1000ms));
QCOMPARE(value, 16); QCOMPARE(value, 16);
} }
@@ -575,8 +577,7 @@ void tst_Async::mapReduce()
QFETCH(double, sum); QFETCH(double, sum);
QFETCH(QList<double>, results); QFETCH(QList<double>, results);
TaskTree tree(root); QVERIFY(TaskTree::runBlocking(root, 1000ms));
QVERIFY(tree.runBlocking(1000));
QCOMPARE(s_results, results); QCOMPARE(s_results, results);
QCOMPARE(s_sum, sum); QCOMPARE(s_sum, sum);
} }

View File

@@ -135,8 +135,7 @@ private slots:
tasks.append(AsyncTask<void>(onSetup(parentDir.filePath(dirName), templateFile))); tasks.append(AsyncTask<void>(onSetup(parentDir.filePath(dirName), templateFile)));
} }
TaskTree taskTree(tasks); QVERIFY(TaskTree::runBlocking(tasks));
QVERIFY(taskTree.runBlocking());
} }
void cleanupTestCase() void cleanupTestCase()
@@ -161,8 +160,7 @@ private slots:
tasks.append(AsyncTask<void>(onSetup(parentDir.filePath(dirName)))); tasks.append(AsyncTask<void>(onSetup(parentDir.filePath(dirName))));
} }
TaskTree taskTree(tasks); QVERIFY(TaskTree::runBlocking(tasks));
QVERIFY(taskTree.runBlocking());
m_tempDir.reset(); m_tempDir.reset();
Singleton::deleteAll(); Singleton::deleteAll();