Add convenience functions for QFuture creation
[ChangeLog][QtCore][QFuture] Add convenience functions to create a ready QFuture and a QFuture with an exception Task-number: QTBUG-86713 Change-Id: Ic7f9ca590a8ea8a9696b84f35bad074780794461 Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io> Reviewed-by: Sona Kurazyan <sona.kurazyan@qt.io>bb10
parent
f61f8bb966
commit
54875be84d
|
|
@ -134,7 +134,12 @@
|
|||
you can attach multiple continuations to a signal, which are invoked in the
|
||||
same thread or a new thread.
|
||||
|
||||
\sa QtFuture::connect(), QFutureWatcher, {Qt Concurrent}
|
||||
A ready QFuture object with a value or a QFuture object holding exception can
|
||||
be created using convenience functions QtFuture::makeReadyFuture and
|
||||
QtFuture::makeExceptionalFuture.
|
||||
|
||||
\sa QtFuture::connect(), QtFuture::makeReadyFuture(),
|
||||
QtFuture::makeExceptionalFuture(), QFutureWatcher, {Qt Concurrent}
|
||||
*/
|
||||
|
||||
/*! \fn template <typename T> QFuture<T>::QFuture()
|
||||
|
|
@ -944,6 +949,107 @@
|
|||
\sa QFuture, QFuture::then()
|
||||
*/
|
||||
|
||||
/*! \fn template<typename T> static QFuture<std::decay_t<T>> QtFuture::makeReadyFuture(T &&value)
|
||||
|
||||
\since 6.1
|
||||
\overload
|
||||
|
||||
Creates and returns a QFuture which already has a result \a value.
|
||||
The returned QFuture has a type of std::decay_t<T>, where T is not void.
|
||||
|
||||
\code
|
||||
auto f = QtFuture::makeReadyFuture(std::make_unique<int>(42));
|
||||
...
|
||||
const int result = *f.takeResult(); // result == 42
|
||||
\endcode
|
||||
|
||||
\sa QFuture, QtFuture::makeExceptionalFuture()
|
||||
*/
|
||||
|
||||
/*! \fn QFuture<void> QtFuture::makeReadyFuture()
|
||||
|
||||
\since 6.1
|
||||
\overload
|
||||
|
||||
Creates and returns a void QFuture. Such QFuture can't store any result.
|
||||
One can use it to query the state of the computation.
|
||||
The returned QFuture will always be in the finished state.
|
||||
|
||||
\code
|
||||
auto f = QtFuture::makeReadyFuture();
|
||||
...
|
||||
const bool started = f.isStarted(); // started == true
|
||||
const bool running = f.isRunning(); // running == false
|
||||
const bool finished = f.isFinished(); // finished == true
|
||||
\endcode
|
||||
|
||||
\sa QFuture, QFuture::isStarted(), QFuture::isRunning(),
|
||||
QFuture::isFinished(), QtFuture::makeExceptionalFuture()
|
||||
*/
|
||||
|
||||
/*! \fn template<typename T> static QFuture<T> QtFuture::makeReadyFuture(const QList<T> &values)
|
||||
|
||||
\since 6.1
|
||||
\overload
|
||||
|
||||
Creates and returns a QFuture which already has multiple results set from \a values.
|
||||
|
||||
\code
|
||||
const QList<int> values { 1, 2, 3 };
|
||||
auto f = QtFuture::makeReadyFuture(values);
|
||||
...
|
||||
const int count = f.resultCount(); // count == 3
|
||||
const auto results = f.results(); // results == { 1, 2, 3 }
|
||||
\endcode
|
||||
|
||||
\sa QFuture, QtFuture::makeExceptionalFuture()
|
||||
*/
|
||||
|
||||
/*! \fn template<typename T> static QFuture<T> QtFuture::makeExceptionalFuture(const QException &exception)
|
||||
|
||||
\since 6.1
|
||||
|
||||
Creates and returns a QFuture which already has an exception \a exception.
|
||||
|
||||
\code
|
||||
QException e;
|
||||
auto f = QtFuture::makeExceptionalFuture<int>(e);
|
||||
...
|
||||
try {
|
||||
f.result(); // throws QException
|
||||
} catch (QException &) {
|
||||
// handle exception here
|
||||
}
|
||||
\endcode
|
||||
|
||||
\sa QFuture, QException, QtFuture::makeReadyFuture()
|
||||
*/
|
||||
|
||||
/*! \fn template<typename T> static QFuture<T> QtFuture::makeExceptionalFuture(std::exception_ptr exception)
|
||||
|
||||
\since 6.1
|
||||
\overload
|
||||
|
||||
Creates and returns a QFuture which already has an exception \a exception.
|
||||
|
||||
\code
|
||||
struct TestException
|
||||
{
|
||||
};
|
||||
...
|
||||
auto exception = std::make_exception_ptr(TestException());
|
||||
auto f = QtFuture::makeExceptionalFuture<int>(exception);
|
||||
...
|
||||
try {
|
||||
f.result(); // throws TestException
|
||||
} catch (TestException &) {
|
||||
// handle exception here
|
||||
}
|
||||
\endcode
|
||||
|
||||
\sa QFuture, QException, QtFuture::makeReadyFuture()
|
||||
*/
|
||||
|
||||
/*! \fn template<class T> template<class Function> QFuture<typename QFuture<T>::ResultType<Function>> QFuture<T>::then(Function &&function)
|
||||
|
||||
\since 6.0
|
||||
|
|
|
|||
|
|
@ -49,6 +49,7 @@
|
|||
#include <QtCore/qglobal.h>
|
||||
#include <QtCore/qfutureinterface.h>
|
||||
#include <QtCore/qthreadpool.h>
|
||||
#include <QtCore/qexception.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
|
|
@ -741,6 +742,68 @@ static QFuture<ArgsType<Signal>> connect(Sender *sender, Signal signal)
|
|||
return promise.future();
|
||||
}
|
||||
|
||||
template<typename T, typename = QtPrivate::EnableForNonVoid<T>>
|
||||
static QFuture<std::decay_t<T>> makeReadyFuture(T &&value)
|
||||
{
|
||||
QFutureInterface<std::decay_t<T>> promise;
|
||||
promise.reportStarted();
|
||||
promise.reportResult(std::forward<T>(value));
|
||||
promise.reportFinished();
|
||||
|
||||
return promise.future();
|
||||
}
|
||||
|
||||
#if defined(Q_CLANG_QDOC)
|
||||
static QFuture<void> makeReadyFuture()
|
||||
#else
|
||||
template<typename T = void>
|
||||
static QFuture<T> makeReadyFuture()
|
||||
#endif
|
||||
{
|
||||
QFutureInterface<T> promise;
|
||||
promise.reportStarted();
|
||||
promise.reportFinished();
|
||||
|
||||
return promise.future();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static QFuture<T> makeReadyFuture(const QList<T> &values)
|
||||
{
|
||||
QFutureInterface<T> promise;
|
||||
promise.reportStarted();
|
||||
promise.reportResults(values);
|
||||
promise.reportFinished();
|
||||
|
||||
return promise.future();
|
||||
}
|
||||
|
||||
#ifndef QT_NO_EXCEPTIONS
|
||||
|
||||
template<typename T = void>
|
||||
static QFuture<T> makeExceptionalFuture(std::exception_ptr exception)
|
||||
{
|
||||
QFutureInterface<T> promise;
|
||||
promise.reportStarted();
|
||||
promise.reportException(exception);
|
||||
promise.reportFinished();
|
||||
|
||||
return promise.future();
|
||||
}
|
||||
|
||||
template<typename T = void>
|
||||
static QFuture<T> makeExceptionalFuture(const QException &exception)
|
||||
{
|
||||
try {
|
||||
exception.raise();
|
||||
} catch (...) {
|
||||
return makeExceptionalFuture<T>(std::current_exception());
|
||||
}
|
||||
Q_UNREACHABLE();
|
||||
}
|
||||
|
||||
#endif // QT_NO_EXCEPTIONS
|
||||
|
||||
} // namespace QtFuture
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
|
|
|||
|
|
@ -156,6 +156,8 @@ private slots:
|
|||
void rejectPendingResultOverwrite_data() { rejectResultOverwrite_data(); }
|
||||
void rejectPendingResultOverwrite();
|
||||
|
||||
void createReadyFutures();
|
||||
|
||||
private:
|
||||
using size_type = std::vector<int>::size_type;
|
||||
|
||||
|
|
@ -3338,5 +3340,72 @@ void tst_QFuture::rejectPendingResultOverwrite()
|
|||
QCOMPARE(f.results(), initResults);
|
||||
}
|
||||
|
||||
void tst_QFuture::createReadyFutures()
|
||||
{
|
||||
// using const T &
|
||||
{
|
||||
const int val = 42;
|
||||
QFuture<int> f = QtFuture::makeReadyFuture(val);
|
||||
QCOMPARE(f.result(), val);
|
||||
}
|
||||
|
||||
// using T
|
||||
{
|
||||
int val = 42;
|
||||
QFuture<int> f = QtFuture::makeReadyFuture(val);
|
||||
QCOMPARE(f.result(), val);
|
||||
}
|
||||
|
||||
// using T &&
|
||||
{
|
||||
auto f = QtFuture::makeReadyFuture(std::make_unique<int>(42));
|
||||
QCOMPARE(*f.takeResult(), 42);
|
||||
}
|
||||
|
||||
// using void
|
||||
{
|
||||
auto f = QtFuture::makeReadyFuture();
|
||||
QVERIFY(f.isStarted());
|
||||
QVERIFY(!f.isRunning());
|
||||
QVERIFY(f.isFinished());
|
||||
}
|
||||
|
||||
// using const QList<T> &
|
||||
{
|
||||
const QList<int> values { 1, 2, 3 };
|
||||
auto f = QtFuture::makeReadyFuture(values);
|
||||
QCOMPARE(f.resultCount(), 3);
|
||||
QCOMPARE(f.results(), values);
|
||||
}
|
||||
|
||||
#ifndef QT_NO_EXCEPTIONS
|
||||
// using QException
|
||||
{
|
||||
QException e;
|
||||
auto f = QtFuture::makeExceptionalFuture<int>(e);
|
||||
bool caught = false;
|
||||
try {
|
||||
f.result();
|
||||
} catch (QException &) {
|
||||
caught = true;
|
||||
}
|
||||
QVERIFY(caught);
|
||||
}
|
||||
|
||||
// using std::exception_ptr and QFuture<void>
|
||||
{
|
||||
auto exception = std::make_exception_ptr(TestException());
|
||||
auto f = QtFuture::makeExceptionalFuture(exception);
|
||||
bool caught = false;
|
||||
try {
|
||||
f.waitForFinished();
|
||||
} catch (TestException &) {
|
||||
caught = true;
|
||||
}
|
||||
QVERIFY(caught);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
QTEST_MAIN(tst_QFuture)
|
||||
#include "tst_qfuture.moc"
|
||||
|
|
|
|||
Loading…
Reference in New Issue