QtPromise integrates with QtConcurrent to simplify chaining QFuture with QPromise.
Converting QFuture<T> to QPromise<T> is done using the QtPromise::resolve
helper:
QFuture<int> future = QtConcurrent::run([]() {
// {...}
return 42;
});
QPromise<int> promise = QtPromise::resolve(future);
or simply:
auto promise = QtPromise::resolve(QtConcurrent::run([]() {
// {...}
}));
Returning a QFuture<T> in then or fail automatically
translate to QPromise<T>:
QPromise<int> input = ...
auto output = input.then([](int res) {
return QtConcurrent::run([]() {
// {...}
return QString{"42"};
});
});
// output type: QPromise<QString>
output.then([](const QString& res) {
// {...}
});
The output promise is resolved when the QFuture is finished.
Exceptions thrown from a QtConcurrent thread reject the associated promise with the exception as the
reason. For this to work, the exception should be a QException
or its subclass. Correct subclassing of QException
includes overriding its methods clone() and
raise(). Without these overrides the promise will
be rejected with QException.
Note that if you throw an exception that is not a subclass of QException, the promise will
be rejected with QUnhandledException
(this restriction only applies to exceptions thrown from a QtConcurrent thread,
read more).
class CustomException : public QException
{
public:
void raise() const override { throw *this; }
CustomException* clone() const override { return new CustomException{*this}; }
};
// {...}
QPromise<int> promise = ...
promise.then([](int res) {
return QtConcurrent::run([]() {
// {...}
if (!success) {
throw CustomException{};
}
return QString{"42"};
});
}).fail([](const CustomException& error) {
// {...}
});