Carson
Carson

Reputation: 3129

How to create an already-resolved future

I have a function that returns a std::future. I have added a cache to the implementation, and I would like to optionally return a value immediately if it does not need to be recalculated.

How can I create an already-resolved future?

// Class declarations shortened to minimal example to communicate intent
class MyClass {
    Cache m_cache;

    std::future<int> foo(int arg);
}

class Cache {
    std::optional<int> get(int arg);
}

std::future<int> MyClass::foo(int arg) {
    if (auto res = m_cache.get(arg)) {
        // *res is my result
        return std::future(*res); // ????? Doesn't work
    }
    // If the cache misses, we need to calculate it
    // Fire up the ol' thread pool and get to work
    return std::launch(std::launch::async /* ommited for brevity */);
}

I'm targeting C++20.

Upvotes: 10

Views: 632

Answers (1)

Artyer
Artyer

Reputation: 40901

Only std::async, std::packaged_task and std::promise can create futures with new states.

std::promise is the easiest way:

std::future<int> MyClass::foo(int arg) {
    if (auto res = m_cache.get(arg)) {
        // *res is my result
        std::promise<int> p;
        p.set_value(*res);
        return p.get_future();
    }
    // If the cache misses, we need to calculate it
    // Fire up the ol' thread pool and get to work
    return std::launch(std::launch::async /* ommited for brevity */);
}
// Or with a helper function
template<typename T>
std::future<std::decay_t<T>> make_ready_future(T&& value) {
    std::promise<std::decay_t<T>> p;
    p.set_value(std::forward<T>(value));
    return p.get_future();
}

std::future<int> MyClass::foo(int arg) {
    if (auto res = m_cache.get(arg)) {
        // *res is my result
        return make_ready_future(*res);
    }
    // If the cache misses, we need to calculate it
    // Fire up the ol' thread pool and get to work
    return std::launch(std::launch::async /* ommited for brevity */);
}

Upvotes: 11

Related Questions