QtConcurrent: Handle running with promise inside QTaskBuilder
Please note, that in case of run with promise it doesn't make sense to provide the overload taking the FutureResult, as if we are going to ignore the returned QFuture object, we can't communicate with the passed QPromise. Fixes: QTBUG-87083 Change-Id: I4066506736c2bbeea3e42030b9495f13e06cb27e Reviewed-by: Sona Kurazyan <sona.kurazyan@qt.io>
This commit is contained in:
parent
cf043a785a
commit
c34673e5d9
@ -129,3 +129,12 @@ QtConcurrent::task([]{ return 42; }).withPriority(10).spawn();
|
||||
//! [11]
|
||||
QtConcurrent::task([]{ qDebug("Hello, world!"); }).spawn(FutureResult::Ignore);
|
||||
//! [11]
|
||||
|
||||
//! [12]
|
||||
void increment(QPromise<int> &promise, int i)
|
||||
{
|
||||
promise.addResult(i + 1);
|
||||
}
|
||||
|
||||
int result = QtConcurrent::task(&increment).withArguments(10).spawn().result(); // result == 11
|
||||
//! [12]
|
||||
|
@ -89,10 +89,11 @@ public:
|
||||
[[nodiscard]]
|
||||
auto spawn()
|
||||
{
|
||||
return (new StoredFunctionCall<Task, Args...>(std::move(taskWithArgs)))
|
||||
->start(startParameters);
|
||||
return TaskResolver<std::decay_t<Task>, std::decay_t<Args>...>::run(
|
||||
std::move(taskWithArgs), startParameters);
|
||||
}
|
||||
|
||||
// We don't want to run with promise when we don't return a QFuture
|
||||
void spawn(FutureResult)
|
||||
{
|
||||
(new StoredFunctionCall<Task, Args...>(std::move(taskWithArgs)))
|
||||
|
@ -148,6 +148,14 @@
|
||||
QtConcurrent::QTaskBuilder::spawn(QtConcurrent::FutureResult::Ignore):
|
||||
|
||||
\snippet code/src_concurrent_qtconcurrenttask.cpp 11
|
||||
|
||||
You can access the promise object associated with the task by defining an
|
||||
additional argument of \c {QPromise<T> &} type inside the function.
|
||||
This additional argument must be the first argument passed to the function, and
|
||||
like in \l {Concurrent Run With Promise} mode, the function is expected to return void type.
|
||||
Result reporting is done through QPromise API:
|
||||
|
||||
\snippet code/src_concurrent_qtconcurrenttask.cpp 12
|
||||
*/
|
||||
|
||||
/*!
|
||||
|
@ -41,9 +41,11 @@ private Q_SLOTS:
|
||||
void taskWithLambda();
|
||||
void taskWithArguments();
|
||||
void useCustomThreadPool();
|
||||
void setPriority_data();
|
||||
void setPriority();
|
||||
void adjustAllSettings();
|
||||
void ignoreFutureResult();
|
||||
void withPromise();
|
||||
};
|
||||
|
||||
using namespace QtConcurrent;
|
||||
@ -59,6 +61,7 @@ void tst_QtConcurrentTask::taskWithFreeFunction()
|
||||
|
||||
QCOMPARE(result, 42);
|
||||
}
|
||||
|
||||
void tst_QtConcurrentTask::taskWithClassMethod()
|
||||
{
|
||||
QString result("foobar");
|
||||
@ -67,6 +70,7 @@ void tst_QtConcurrentTask::taskWithClassMethod()
|
||||
|
||||
QCOMPARE(result, "foo");
|
||||
}
|
||||
|
||||
void tst_QtConcurrentTask::taskWithCallableObject()
|
||||
{
|
||||
QCOMPARE(task(std::plus<int>())
|
||||
@ -100,8 +104,18 @@ void tst_QtConcurrentTask::useCustomThreadPool()
|
||||
QCOMPARE(result, 42);
|
||||
}
|
||||
|
||||
void tst_QtConcurrentTask::setPriority_data()
|
||||
{
|
||||
QTest::addColumn<bool>("runWithPromise");
|
||||
|
||||
QTest::addRow("without promise") << false;
|
||||
QTest::addRow("with promise") << true;
|
||||
}
|
||||
|
||||
void tst_QtConcurrentTask::setPriority()
|
||||
{
|
||||
QFETCH(bool, runWithPromise);
|
||||
|
||||
QThreadPool pool;
|
||||
pool.setMaxThreadCount(1);
|
||||
|
||||
@ -115,15 +129,25 @@ void tst_QtConcurrentTask::setPriority()
|
||||
const int tasksCount = 10;
|
||||
QList<int> priorities(tasksCount);
|
||||
std::iota(priorities.begin(), priorities.end(), 1);
|
||||
auto seed = std::chrono::system_clock::now().time_since_epoch().count();
|
||||
auto seed = std::random_device {}();
|
||||
std::shuffle(priorities.begin(), priorities.end(), std::default_random_engine(seed));
|
||||
|
||||
qDebug() << "Generated priorities list" << priorities << "using seed" << seed;
|
||||
|
||||
QList<int> actual;
|
||||
for (int priority : priorities)
|
||||
futureResults << task([priority, &actual] { actual << priority; })
|
||||
.onThreadPool(pool)
|
||||
.withPriority(priority)
|
||||
.spawn();
|
||||
for (int priority : priorities) {
|
||||
if (runWithPromise) {
|
||||
futureResults << task([priority, &actual] (QPromise<void> &) { actual << priority; })
|
||||
.onThreadPool(pool)
|
||||
.withPriority(priority)
|
||||
.spawn();
|
||||
} else {
|
||||
futureResults << task([priority, &actual] { actual << priority; })
|
||||
.onThreadPool(pool)
|
||||
.withPriority(priority)
|
||||
.spawn();
|
||||
}
|
||||
}
|
||||
|
||||
sem.release();
|
||||
pool.waitForDone();
|
||||
@ -156,6 +180,7 @@ void tst_QtConcurrentTask::adjustAllSettings()
|
||||
|
||||
QCOMPARE(result, QList<int>({ 1, 2, 3 }));
|
||||
}
|
||||
|
||||
void tst_QtConcurrentTask::ignoreFutureResult()
|
||||
{
|
||||
QThreadPool pool;
|
||||
@ -171,5 +196,23 @@ void tst_QtConcurrentTask::ignoreFutureResult()
|
||||
QCOMPARE(value, 10);
|
||||
}
|
||||
|
||||
void incrementWithPromise(QPromise<int> &promise, int i)
|
||||
{
|
||||
promise.addResult(i + 1);
|
||||
}
|
||||
|
||||
void return0WithPromise(QPromise<int> &promise)
|
||||
{
|
||||
promise.addResult(0);
|
||||
}
|
||||
|
||||
void tst_QtConcurrentTask::withPromise()
|
||||
{
|
||||
QCOMPARE(task(&return0WithPromise).spawn().result(), 0);
|
||||
QCOMPARE(task(&return0WithPromise).withPriority(7).spawn().result(), 0);
|
||||
QCOMPARE(task(&incrementWithPromise).withArguments(1).spawn().result(), 2);
|
||||
QCOMPARE(task(&incrementWithPromise).withArguments(1).withPriority(7).spawn().result(), 2);
|
||||
}
|
||||
|
||||
QTEST_MAIN(tst_QtConcurrentTask)
|
||||
#include "tst_qtconcurrenttask.moc"
|
||||
|
Loading…
x
Reference in New Issue
Block a user