forked from qt-creator/qt-creator
runextensions: Add convenience method for result handler
Change-Id: Ibe7e62049f165276fdedcd04d8311324f6bc5d19 Reviewed-by: Tobias Hunger <tobias.hunger@qt.io>
This commit is contained in:
@@ -31,6 +31,7 @@
|
|||||||
#include <QCoreApplication>
|
#include <QCoreApplication>
|
||||||
#include <QFuture>
|
#include <QFuture>
|
||||||
#include <QFutureInterface>
|
#include <QFutureInterface>
|
||||||
|
#include <QFutureWatcher>
|
||||||
#include <QRunnable>
|
#include <QRunnable>
|
||||||
#include <QThread>
|
#include <QThread>
|
||||||
#include <QThreadPool>
|
#include <QThreadPool>
|
||||||
@@ -493,4 +494,58 @@ runAsync(QThreadPool *pool, Function &&function, Args&&... args)
|
|||||||
std::forward<Args>(args)...);
|
std::forward<Args>(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 <typename R, typename T>
|
||||||
|
const QFuture<T> &onResultReady(const QFuture<T> &future, R *receiver, void(R::*member)(const T &))
|
||||||
|
{
|
||||||
|
auto watcher = new QFutureWatcher<T>();
|
||||||
|
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 <typename T, typename Function>
|
||||||
|
const QFuture<T> &onResultReady(const QFuture<T> &future, QObject *guard, Function f)
|
||||||
|
{
|
||||||
|
auto watcher = new QFutureWatcher<T>();
|
||||||
|
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 <typename T, typename Function>
|
||||||
|
const QFuture<T> &onResultReady(const QFuture<T> &future, Function f)
|
||||||
|
{
|
||||||
|
auto watcher = new QFutureWatcher<T>();
|
||||||
|
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
|
} // Utils
|
||||||
|
@@ -44,6 +44,7 @@ private slots:
|
|||||||
void threadPriority();
|
void threadPriority();
|
||||||
void runAsyncNoFutureInterface();
|
void runAsyncNoFutureInterface();
|
||||||
void crefFunction();
|
void crefFunction();
|
||||||
|
void onResultReady();
|
||||||
};
|
};
|
||||||
|
|
||||||
void report3(QFutureInterface<int> &fi)
|
void report3(QFutureInterface<int> &fi)
|
||||||
@@ -557,6 +558,64 @@ void tst_RunExtensions::crefFunction()
|
|||||||
QCOMPARE(value, true);
|
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<QString> f = Utils::runAsync([](QFutureInterface<QString> &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<QString> f = Utils::runAsync([](QFutureInterface<QString> &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<QString> 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)
|
QTEST_MAIN(tst_RunExtensions)
|
||||||
|
|
||||||
#include "tst_runextensions.moc"
|
#include "tst_runextensions.moc"
|
||||||
|
Reference in New Issue
Block a user