QtFuture Namespace▲
-
Header: QFuture
-
CMake:
find_package(Qt6 REQUIRED COMPONENTS Core)
target_link_libraries(mytarget PRIVATE Qt6::Core)
-
qmake: QT += core
Detailed Description▲
Classes▲
[since 6.3] QtFuture::WhenAnyResult▲
The QtFuture::WhenAnyResult<T> struct is used for packaging the copy and the index of the first completed QFuture<T> in the sequence of futures packaging type T that are passed to QtFuture::whenAny().
This struct was introduced in Qt 6.3.
See Also▲
See also QFuture, QtFuture::whenAny()
Type Documentation▲
[since 6.0] enum QtFuture::Launch▲
Represents execution policies for running a QFuture continuation.
Constant |
Value |
Description |
---|---|---|
QtFuture::Launch::Sync |
0 |
The continuation will be launched in the same thread that fulfills the promise associated with the future to which the continuation was attached, or if it has already finished, the continuation will be invoked immediately, in the thread that executes then(). |
QtFuture::Launch::Async |
1 |
The continuation will be launched in a separate thread taken from the global QThreadPool. |
QtFuture::Launch::Inherit |
2 |
The continuation will inherit the launch policy or thread pool of the future to which it is attached. |
Sync is used as a default launch policy.
This enum was introduced or modified in Qt 6.0.
See Also▲
See also QFuture::then(), QThreadPool::globalInstance()
Function Documentation▲
QFuture<ArgsType<Signal>> QtFuture::connect(Sender *sender, Signal signal)▲
Creates and returns a QFuture which will become available when the sender emits the signal. If the signal takes no arguments, a QFuture<void> is returned. If the signal takes a single argument, the resulted QFuture will be filled with the signal's argument value. If the signal takes multiple arguments, the resulted QFuture is filled with std::tuple storing the values of signal's arguments. If the sender is destroyed before the signal is emitted, the resulted QFuture will be canceled.
For example, let's say we have the following object:
class
Object : public
QObject
{
Q_OBJECT
...
signals
:
void
noArgSignal();
void
singleArgSignal(int
value);
void
multipleArgs(int
value1, double
value2, const
QString &
amp;value3);
}
;
We can connect its signals to QFuture objects in the following way:
Object object;
QFuture&
lt;void
&
gt; voidFuture =
QtFuture::
connect(&
amp;object, &
amp;Object::
noArgSignal);
QFuture&
lt;int
&
gt; intFuture =
QtFuture::
connect(&
amp;object, &
amp;Object::
singleArgSignal);
using
Args =
std::
tuple&
lt;int
, double
, QString&
gt;;
QFuture&
lt;Args&
gt; tupleFuture =
QtFuture::
connect(&
amp;object, &
amp;Object::
multipleArgs)
We can also chain continuations to be run when a signal is emitted:
QtFuture::
connect(&
amp;object, &
amp;Object::
singleArgSignal).then([](int
value) {
// do something with the value
}
);
You can also start the continuation in a new thread or a custom thread pool using QtFuture::Launch policies. For example:
QtFuture::
connect(&
amp;object, &
amp;Object::
singleArgSignal).then(QtFuture::Launch::
Async, [](int
value) {
// this will run in a new thread
}
);
Throwing an exception from a slot invoked by Qt's signal-slot connection is considered to be an undefined behavior, if it is not handled within the slot. But with QFuture::connect(), you can throw and handle exceptions from the continuations:
QtFuture::
connect(&
amp;object, &
amp;Object::
singleArgSignal).then([](int
value) {
...
throw
std::
exception();
...
}
).onFailed([](const
std::
exception &
amp;e) {
// handle the exception
}
).onFailed([] {
// handle other exceptions
}
);
The connected future will be fulfilled only once, when the signal is emitted for the first time.
See Also▲
See also QFuture, QFuture::then()
[since 6.1] QFuture<T> QtFuture::makeExceptionalFuture(const QException &exception)▲
Creates and returns a QFuture which already has an exception exception.
QException e;
auto
f =
QtFuture::
makeExceptionalFuture&
lt;int
&
gt;(e);
...
try
{
f.result(); // throws QException
}
catch
(QException &
amp;) {
// handle exception here
}
This function was introduced in Qt 6.1.
See Also▲
See also QFuture, QException, QtFuture::makeReadyFuture()
[since 6.1] QFuture<T> QtFuture::makeExceptionalFuture(std::exception_ptr exception)▲
This is an overloaded function.
Creates and returns a QFuture which already has an exception exception.
struct
TestException
{
}
;
...
auto
exception =
std::
make_exception_ptr(TestException());
auto
f =
QtFuture::
makeExceptionalFuture&
lt;int
&
gt;(exception);
...
try
{
f.result(); // throws TestException
}
catch
(TestException &
amp;) {
// handle exception here
}
This function was introduced in Qt 6.1.
See Also▲
See also QFuture, QException, QtFuture::makeReadyFuture()
[since 6.1] QFuture<std::decay_t<T>> QtFuture::makeReadyFuture(T &&value)▲
This is an overloaded function.
Creates and returns a QFuture which already has a result value. The returned QFuture has a type of std::decay_t<T>, where T is not void.
auto
f =
QtFuture::
makeReadyFuture(std::
make_unique&
lt;int
&
gt;(42
));
...
const
int
result =
*
f.takeResult(); // result == 42
This function was introduced in Qt 6.1.
See Also▲
See also QFuture, QtFuture::makeExceptionalFuture()
[since 6.1] QFuture<void> QtFuture::makeReadyFuture()▲
This is an overloaded function.
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.
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
This function was introduced in Qt 6.1.
See Also▲
See also QFuture, QFuture::isStarted(), QFuture::isRunning(), QFuture::isFinished(), QtFuture::makeExceptionalFuture()
[since 6.1] QFuture<T> QtFuture::makeReadyFuture(const QList<T> &values)▲
This is an overloaded function.
Creates and returns a QFuture which already has multiple results set from values.
const
QList&
lt;int
&
gt; 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 }
This function was introduced in Qt 6.1.
See Also▲
See also QFuture, QtFuture::makeExceptionalFuture()
[since 6.3] QFuture<OutputSequence> QtFuture::whenAll(InputIt first, InputIt last)▲
Returns a new QFuture that succeeds when all futures from first to last complete. first and last are iterators to a sequence of futures packaging type T. OutputSequence is a sequence containing all completed futures from first to last, appearing in the same order as in the input. If the type of OutputSequence is not specified, the resulting futures will be returned in a QList of QFuture<T>. For example:
QList&
lt;QFuture&
lt;int
&
gt;&
gt; inputFutures {
...}
;
// whenAll has type QFuture<QList<QFuture<int>>>
auto
whenAll =
QtFuture::
whenAll(inputFutures.begin(), inputFutures.end());
// whenAllVector has type QFuture<std::vector<QFuture<int>>>
auto
whenAllVector =
QtFuture::
whenAll&
lt;std::
vector&
lt;QFuture&
lt;int
&
gt;&
gt;&
gt;(inputFutures.begin(), inputFutures.end());
The output sequence must support random access and the resize() operation.
If first equals last, this function returns a ready QFuture that contains an empty OutputSequence.
The returned future always completes successfully after all the specified futures complete. It doesn't matter if any of these futures completes with error or is canceled. You can use .then() to process the completed futures after the future returned by whenAll() succeeds:
QList&
lt;QFuture&
lt;int
&
gt;&
gt; inputFutures {
...}
;
QtFuture::
whenAll(inputFutures.begin(), inputFutures.end())
.then([](const
QList&
lt;QFuture&
lt;int
&
gt;&
gt; &
amp;results) {
for
(auto
future : results) {
if
(future.isCanceled())
// handle the cancellation (possibly due to an exception)
else
// do something with the result
}
}
);
If the input futures complete on different threads, the future returned by this method will complete in the thread that the last future completes in. Therefore, the continuations attached to the future returned by whenAll() cannot always make assumptions about which thread they will be run on. Use the overload of .then() that takes a context object if you want to control which thread the continuations are invoked on.
This function was introduced in Qt 6.3.
[since 6.3] QFuture<OutputSequence> QtFuture::whenAll(Futures &&... futures)▲
Returns a new QFuture that succeeds when all futures packaging arbitrary types complete. OutputSequence is a sequence of completed futures. The type of its entries is std::variant<Futures...>. For each QFuture<T> passed to whenAll(), the entry at the corresponding position in OutputSequence will be a std::variant holding that QFuture<T>, in its completed state. If the type of OutputSequence is not specified, the resulting futures will be returned in a QList of std::variant<Futures...>. For example:
QFuture&
lt;int
&
gt; intFuture =
...;
QFuture&
lt;QString&
gt; stringFuture =
...;
QFuture&
lt;void
&
gt; voidFuture =
...;
using
FuturesVariant =
std::
variant&
lt;QFuture&
lt;int
&
gt;, QFuture&
lt;QString&
gt;, QFuture&
lt;void
&
gt;&
gt;;
// whenAll has type QFuture<QList<FuturesVariant>>
auto
whenAll =
QtFuture::
whenAll(intFuture, stringFuture, voidFuture);
// whenAllVector has type QFuture<std::vector<FuturesVariant>>
auto
whenAllVector =
QtFuture::
whenAll&
lt;std::
vector&
lt;FuturesVariant&
gt;&
gt;(intFuture, stringFuture, voidFuture);
The output sequence should support random access and the resize() operation.
The returned future always completes successfully after all the specified futures complete. It doesn't matter if any of these futures completes with error or is canceled. You can use .then() to process the completed futures after the future returned by whenAll() succeeds:
QFuture&
lt;int
&
gt; intFuture =
...;
QFuture&
lt;QString&
gt; stringFuture =
...;
QFuture&
lt;void
&
gt; voidFuture =
...;
using
FuturesVariant =
std::
variant&
lt;QFuture&
lt;int
&
gt;, QFuture&
lt;QString&
gt;, QFuture&
lt;void
&
gt;&
gt;;
QtFuture::
whenAll(intFuture, stringFuture, voidFuture)
.then([](const
QList&
lt;FuturesVariant&
gt; &
amp;results) {
...
for
(auto
result : results)
{
// assuming handleResult() is overloaded based on the QFuture type
std::
visit([](auto
&
amp;&
amp;future) {
handleResult(future); }
, result);
}
...
}
);
If the input futures complete on different threads, the future returned by this method will complete in the thread that the last future completes in. Therefore, the continuations attached to the future returned by whenAll() cannot always make assumptions about which thread they will be run on. Use the overload of .then() that takes a context object if you want to control which thread the continuations are invoked on.
This function was introduced in Qt 6.3.
[since 6.3] QFuture<QtFuture::WhenAnyResult<T>> QtFuture::whenAny(InputIt first, InputIt last)▲
Returns a new QFuture that succeeds when any of the futures from first to last completes. first and last are iterators to a sequence of futures packaging type T. The returned future packages a value of type QtFuture::WhenAnyResult<T> which in turn packages the index of the first completed QFuture and the QFuture itself. If first equals last, this function returns a ready QFuture that has -1 for the index field in the QtFuture::WhenAnyResult struct and a default-constructed QFuture<T> for the future field. Note that a default-constructed QFuture is a completed future in a cancelled state.
The returned future always completes successfully after the first future from the specified futures completes. It doesn't matter if the first future completes with error or is canceled. You can use .then() to process the result after the future returned by whenAny() succeeds:
QList&
lt;QFuture&
lt;int
&
gt;&
gt; inputFutures =
...;
QtFuture::
whenAny(inputFutures.begin(), inputFutures.end())
.then([](const
QtFuture::
WhenAnyResult&
lt;int
&
gt; &
amp;result) {
qsizetype index =
result.index;
QFuture&
lt;int
&
gt; future =
result.future;
// ...
}
);
If the input futures complete on different threads, the future returned by this method will complete in the thread that the first future completes in. Therefore, the continuations attached to the future returned by whenAny() cannot always make assumptions about which thread they will be run on. Use the overload of .then() that takes a context object if you want to control which thread the continuations are invoked on.
This function was introduced in Qt 6.3.
See Also▲
See also QtFuture::WhenAnyResult
[since 6.3] QFuture<std::variant<std::decay_t<Futures>...>> QtFuture::whenAny(Futures &&... futures)▲
Returns a new QFuture that succeeds when any of the futures completes. futures can package arbitrary types. The returned future packages the value of type std::variant<Futures...> which in turn packages the first completed QFuture from futures. You can use std::variant::index() to find out the index of the future in the sequence of futures that finished first.
The returned future always completes successfully after the first future from the specified futures completes. It doesn't matter if the first future completes with error or is canceled. You can use .then() to process the result after the future returned by whenAny() succeeds:
QFuture&
lt;int
&
gt; intFuture =
...;
QFuture&
lt;QString&
gt; stringFuture =
...;
QFuture&
lt;void
&
gt; voidFuture =
...;
using
FuturesVariant =
std::
variant&
lt;QFuture&
lt;int
&
gt;, QFuture&
lt;QString&
gt;, QFuture&
lt;void
&
gt;&
gt;;
QtFuture::
whenAny(intFuture, stringFuture, voidFuture).then([](const
FuturesVariant &
amp;result) {
...
// assuming handleResult() is overloaded based on the QFuture type
std::
visit([](auto
&
amp;&
amp;future) {
handleResult(future); }
, result);
...
}
);
If the input futures complete on different threads, the future returned by this method will complete in the thread that the first future completes in. Therefore, the continuations attached to the future returned by whenAny() cannot always make assumptions about which thread they will be run on. Use the overload of .then() that takes a context object if you want to control which thread the continuations are invoked on.
This function was introduced in Qt 6.3.