diff --git a/src/libs/utils/runextensions.h b/src/libs/utils/runextensions.h index 43a25411d6e..0ba0b8c3c53 100644 --- a/src/libs/utils/runextensions.h +++ b/src/libs/utils/runextensions.h @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include @@ -493,4 +494,58 @@ runAsync(QThreadPool *pool, Function &&function, Args&&... args) std::forward(args)...); } + +/*! + Adds a handler for when a result is ready. + This creates a new QFutureWatcher. Do not use if you intend to react on multiple conditions + or create a QFutureWatcher already for other reasons. +*/ +template +const QFuture &onResultReady(const QFuture &future, R *receiver, void(R::*member)(const T &)) +{ + auto watcher = new QFutureWatcher(); + watcher->setFuture(future); + QObject::connect(watcher, &QFutureWatcherBase::finished, watcher, &QObject::deleteLater); + QObject::connect(watcher, &QFutureWatcherBase::resultReadyAt, receiver, + [receiver, member, watcher](int index) { + (receiver->*member)(watcher->future().resultAt(index)); + }); + return future; +} + +/*! + Adds a handler for when a result is ready. The guard object determines the lifetime of + the connection. + This creates a new QFutureWatcher. Do not use if you intend to react on multiple conditions + or create a QFutureWatcher already for other reasons. +*/ +template +const QFuture &onResultReady(const QFuture &future, QObject *guard, Function f) +{ + auto watcher = new QFutureWatcher(); + watcher->setFuture(future); + QObject::connect(watcher, &QFutureWatcherBase::finished, watcher, &QObject::deleteLater); + QObject::connect(watcher, &QFutureWatcherBase::resultReadyAt, guard, [f, watcher](int index) { + f(watcher->future().resultAt(index)); + }); + return future; +} + +/*! + Adds a handler for when a result is ready. + This creates a new QFutureWatcher. Do not use if you intend to react on multiple conditions + or create a QFutureWatcher already for other reasons. +*/ +template +const QFuture &onResultReady(const QFuture &future, Function f) +{ + auto watcher = new QFutureWatcher(); + watcher->setFuture(future); + QObject::connect(watcher, &QFutureWatcherBase::finished, watcher, &QObject::deleteLater); + QObject::connect(watcher, &QFutureWatcherBase::resultReadyAt, [f, watcher](int index) { + f(watcher->future().resultAt(index)); + }); + return future; +} + } // Utils diff --git a/tests/auto/runextensions/tst_runextensions.cpp b/tests/auto/runextensions/tst_runextensions.cpp index f1d77fa0605..acad21b15d2 100644 --- a/tests/auto/runextensions/tst_runextensions.cpp +++ b/tests/auto/runextensions/tst_runextensions.cpp @@ -44,6 +44,7 @@ private slots: void threadPriority(); void runAsyncNoFutureInterface(); void crefFunction(); + void onResultReady(); }; void report3(QFutureInterface &fi) @@ -557,6 +558,64 @@ void tst_RunExtensions::crefFunction() QCOMPARE(value, true); } +class ObjWithProperty : public QObject +{ + Q_OBJECT + +public slots: + void setValue(const QString &s) + { + value = s; + } + +public: + QString value; +}; + +void tst_RunExtensions::onResultReady() +{ + { // lambda + QFuture f = Utils::runAsync([](QFutureInterface &fi) { + fi.reportResult("Hi"); + fi.reportResult("there"); + }); + int count = 0; + QString res; + Utils::onResultReady(f, [&count, &res](const QString &s) { + ++count; + res = s; + }); + f.waitForFinished(); + QCoreApplication::processEvents(); + QCOMPARE(count, 2); + QCOMPARE(res, QString("there")); + } + { // lambda with guard + QFuture f = Utils::runAsync([](QFutureInterface &fi) { + fi.reportResult("Hi"); + fi.reportResult("there"); + }); + int count = 0; + ObjWithProperty obj; + Utils::onResultReady(f, &obj, [&count, &obj](const QString &s) { + ++count; + obj.setValue(s); + }); + f.waitForFinished(); + QCoreApplication::processEvents(); + QCOMPARE(count, 2); + QCOMPARE(obj.value, QString("there")); + } + { // member + QFuture f = Utils::runAsync([]() { return QString("Hi"); }); + ObjWithProperty obj; + Utils::onResultReady(f, &obj, &ObjWithProperty::setValue); + f.waitForFinished(); + QCoreApplication::processEvents(); + QCOMPARE(obj.value, QString("Hi")); + } +} + QTEST_MAIN(tst_RunExtensions) #include "tst_runextensions.moc"