Revision control

Copy as Markdown

// Copyright (C) 2020 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
// Note: this file is published under a license that is different from a default
// test sources license. This is intentional to comply with default
// snippet license.
#include <QCoreApplication>
#include <QTest>
#include <qfuture.h>
#include <qfuturewatcher.h>
#include <qpromise.h>
#include <memory>
class snippet_QPromise
{
public:
static void basicExample();
static void multithreadExample();
static void suspendExample();
};
void snippet_QPromise::basicExample()
{
#if QT_CONFIG(cxx11_future)
//! [basic]
QPromise<int> promise;
QFuture<int> future = promise.future();
const std::unique_ptr<QThread> thread(QThread::create([] (QPromise<int> promise) {
promise.start(); // notifies QFuture that the computation is started
promise.addResult(42);
promise.finish(); // notifies QFuture that the computation is finished
}, std::move(promise)));
thread->start();
future.waitForFinished(); // blocks until QPromise::finish is called
future.result(); // returns 42
//! [basic]
QCOMPARE(future.result(), 42);
thread->wait();
#endif
}
void snippet_QPromise::multithreadExample()
{
#if QT_CONFIG(cxx11_future)
//! [multithread_init]
const auto sharedPromise = std::make_shared<QPromise<int>>();
QFuture<int> future = sharedPromise->future();
// ...
sharedPromise->start();
//! [multithread_init]
//! [multithread_main]
// here, QPromise is shared between threads via a smart pointer
const std::unique_ptr<QThread> threads[] = {
std::unique_ptr<QThread>(QThread::create([] (auto sharedPromise) {
sharedPromise->addResult(0, 0); // adds value 0 by index 0
}, sharedPromise)),
std::unique_ptr<QThread>(QThread::create([] (auto sharedPromise) {
sharedPromise->addResult(-1, 1); // adds value -1 by index 1
}, sharedPromise)),
std::unique_ptr<QThread>(QThread::create([] (auto sharedPromise) {
sharedPromise->addResult(-2, 2); // adds value -2 by index 2
}, sharedPromise)),
// ...
};
// start all threads
for (auto& t : threads)
t->start();
// ...
future.resultAt(0); // waits until result at index 0 becomes available. returns value 0
future.resultAt(1); // waits until result at index 1 becomes available. returns value -1
future.resultAt(2); // waits until result at index 2 becomes available. returns value -2
//! [multithread_main]
QCOMPARE(future.resultAt(0), 0);
QCOMPARE(future.resultAt(1), -1);
QCOMPARE(future.resultAt(2), -2);
for (auto& t : threads)
t->wait();
//! [multithread_cleanup]
sharedPromise->finish();
//! [multithread_cleanup]
#endif
}
void snippet_QPromise::suspendExample()
{
#if QT_CONFIG(cxx11_future)
//! [suspend_start]
// Create promise and future
QPromise<int> promise;
QFuture<int> future = promise.future();
promise.start();
// Start a computation thread that supports suspension and cancellation
const std::unique_ptr<QThread> thread(QThread::create([] (QPromise<int> promise) {
for (int i = 0; i < 100; ++i) {
promise.addResult(i);
promise.suspendIfRequested(); // support suspension
if (promise.isCanceled()) // support cancellation
break;
}
promise.finish();
}, std::move(promise)));
thread->start();
//! [suspend_start]
//! [suspend_suspend]
future.suspend();
//! [suspend_suspend]
// wait in calling thread until future.isSuspended() becomes true or do
// something meanwhile
while (!future.isSuspended()) {
QThread::msleep(50);
}
//! [suspend_intermediateResults]
future.resultCount(); // returns some number between 0 and 100
for (int i = 0; i < future.resultCount(); ++i) {
// process results available before suspension
}
//! [suspend_intermediateResults]
// at least one result is available due to the logic inside a thread
QVERIFY(future.resultCount() > 0);
QVERIFY(future.resultCount() <= 100);
for (int i = 0; i < future.resultCount(); ++i) {
QCOMPARE(future.resultAt(i), i);
}
//! [suspend_end]
future.resume(); // resumes computation, this call will unblock the promise
// alternatively, call future.cancel() to stop the computation
future.waitForFinished();
future.results(); // returns all computation results - array of values from 0 to 99
//! [suspend_end]
thread->wait();
QCOMPARE(future.resultCount(), 100);
QList<int> expected(100);
std::iota(expected.begin(), expected.end(), 0);
QCOMPARE(future.results(), expected);
#endif
}