# Qt Concurrent

QtPromise integrates with QtConcurrent (opens new window) 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 (opens new window).

# 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 (opens new window) or its subclass. Correct subclassing of QException (opens new window) includes overriding its methods clone() (opens new window) and raise() (opens new window). Without these overrides the promise will be rejected with QException (opens new window).

Note that if you throw an exception that is not a subclass of QException, the promise will be rejected with QUnhandledException (opens new window) (this restriction only applies to exceptions thrown from a QtConcurrent thread, read more (opens new window)).

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