qtconcurrent.md 2.4 KB

Qt Concurrent

QtPromise integrates with QtConcurrent to simplify chaining QFuture with QPromise.

Convert

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([]() {
    // {...}
}));

Chain

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.

Error

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) {
    // {...}
});