Futures vs. Promises

C++C++11PromiseFuture

C++ Problem Overview


I'm confusing myself with difference between a future and a promise.

Obviously, they have different methods and stuff, but what is the actual use case?

Is it?:

  • when I'm managing some async task, I use future to get the value "in future"
  • when I'm the async task, I use promise as the return type to allow the user get a future from my promise

C++ Solutions


Solution 1 - C++

Future and Promise are the two separate sides of an asynchronous operation.

std::promise is used by the "producer/writer" of the asynchronous operation.

std::future is used by the "consumer/reader" of the asynchronous operation.

The reason it is separated into these two separate "interfaces" is to hide the "write/set" functionality from the "consumer/reader".

auto promise = std::promise<std::string>();

auto producer = std::thread([&]
{
	promise.set_value("Hello World");
});

auto future = promise.get_future();

auto consumer = std::thread([&]
{
	std::cout << future.get();
});

producer.join();
consumer.join();

One (incomplete) way to implement std::async using std::promise could be:

template<typename F>
auto async(F&& func) -> std::future<decltype(func())>
{
    typedef decltype(func()) result_type;

    auto promise = std::promise<result_type>();
    auto future  = promise.get_future();

    std::thread(std::bind([=](std::promise<result_type>& promise)
    {
        try
        {
            promise.set_value(func()); // Note: Will not work with std::promise<void>. Needs some meta-template programming which is out of scope for this question.
        }
        catch(...)
        {
            promise.set_exception(std::current_exception());
        }
    }, std::move(promise))).detach();

    return std::move(future);
}

Using std::packaged_task which is a helper (i.e. it basically does what we were doing above) around std::promise you could do the following which is more complete and possibly faster:

template<typename F>
auto async(F&& func) -> std::future<decltype(func())>
{
    auto task   = std::packaged_task<decltype(func())()>(std::forward<F>(func));
    auto future = task.get_future();

    std::thread(std::move(task)).detach();

    return std::move(future);
}

Note that this is slightly different from std::async where the returned std::future will when destructed actually block until the thread is finished.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionŠimon T&#243;thView Question on Stackoverflow
Solution 1 - C++ronagView Answer on Stackoverflow