forked from qt-creator/qt-creator
TaskTree: Add runBlocking() helpers
To be used in non-main threads and in autotests. Change-Id: If37be854f65c9cfe94eb781a28dc8db4365809e1 Reviewed-by: <github-actions-qt-creator@cristianadam.eu> Reviewed-by: hjk <hjk@qt.io> Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
This commit is contained in:
@@ -3,7 +3,10 @@
|
|||||||
|
|
||||||
#include "tasktree.h"
|
#include "tasktree.h"
|
||||||
|
|
||||||
|
#include <QEventLoop>
|
||||||
|
#include <QFutureWatcher>
|
||||||
#include <QSet>
|
#include <QSet>
|
||||||
|
#include <QTimer>
|
||||||
|
|
||||||
namespace Tasking {
|
namespace Tasking {
|
||||||
|
|
||||||
@@ -1444,6 +1447,54 @@ 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)
|
||||||
|
{
|
||||||
|
if (isRunning() || future.isCanceled())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
bool ok = false;
|
||||||
|
QEventLoop loop;
|
||||||
|
|
||||||
|
const auto finalize = [&loop, &ok](bool success) {
|
||||||
|
ok = success;
|
||||||
|
// Otherwise, the tasks from inside the running tree that were deleteLater()
|
||||||
|
// will be leaked. Refer to the QObject::deleteLater() docs.
|
||||||
|
QMetaObject::invokeMethod(&loop, [&loop] { loop.quit(); }, Qt::QueuedConnection);
|
||||||
|
};
|
||||||
|
|
||||||
|
QFutureWatcher<void> watcher;
|
||||||
|
connect(&watcher, &QFutureWatcherBase::canceled, this, &TaskTree::stop);
|
||||||
|
watcher.setFuture(future);
|
||||||
|
|
||||||
|
connect(this, &TaskTree::done, &loop, [finalize] { finalize(true); });
|
||||||
|
connect(this, &TaskTree::errorOccurred, &loop, [finalize] { finalize(false); });
|
||||||
|
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);
|
||||||
|
if (!ok) {
|
||||||
|
auto nonConstFuture = future;
|
||||||
|
nonConstFuture.cancel();
|
||||||
|
}
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TaskTree::runBlocking(int timeoutMs)
|
||||||
|
{
|
||||||
|
QPromise<void> dummy;
|
||||||
|
dummy.start();
|
||||||
|
return runBlocking(dummy.future(), timeoutMs);
|
||||||
|
}
|
||||||
|
|
||||||
int TaskTree::taskCount() const
|
int TaskTree::taskCount() const
|
||||||
{
|
{
|
||||||
return d->m_root ? d->m_root->taskCount() : 0;
|
return d->m_root ? d->m_root->taskCount() : 0;
|
||||||
|
@@ -9,6 +9,11 @@
|
|||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QSharedPointer>
|
#include <QSharedPointer>
|
||||||
|
|
||||||
|
QT_BEGIN_NAMESPACE
|
||||||
|
template <class T>
|
||||||
|
class QFuture;
|
||||||
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
namespace Tasking {
|
namespace Tasking {
|
||||||
|
|
||||||
class ExecutionContextActivator;
|
class ExecutionContextActivator;
|
||||||
@@ -369,6 +374,12 @@ public:
|
|||||||
void stop();
|
void stop();
|
||||||
bool isRunning() const;
|
bool isRunning() const;
|
||||||
|
|
||||||
|
// Helper methods. They execute a local event loop with ExcludeUserInputEvents.
|
||||||
|
// 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.
|
||||||
|
bool runBlocking(const QFuture<void> &future, int timeoutMs = 0);
|
||||||
|
bool runBlocking(int timeoutMs = 0);
|
||||||
|
|
||||||
int taskCount() const;
|
int taskCount() const;
|
||||||
int progressMaximum() const { return taskCount(); }
|
int progressMaximum() const { return taskCount(); }
|
||||||
int progressValue() const; // all finished / skipped / stopped tasks, groups itself excluded
|
int progressValue() const; // all finished / skipped / stopped tasks, groups itself excluded
|
||||||
|
Reference in New Issue
Block a user