Futures vs. Promises
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.
Related videos on Youtube
Šimon Tóth
Backend oriented Software developer and Researcher with industry experience starting in 2004.
Updated on January 27, 2020Comments
-
Šimon Tóth over 4 years
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
-
Kerrek SB over 11 yearsI wrote a bit about this in this answer.
-
bobobobo over 2 yearsDoes this answer your question? What is std::promise?
-
polkovnikov.ph almost 8 years@taras suggests that returning
std::move(something)
is useless and it also hurts (N)RVO. Reverting his edit. -
Damian almost 8 yearsIn Visual Studio 2015 please use std::cout << future.get().c_str();
-
kawing-chiu over 7 yearsFor those who are still confused, see this answer.
-
Martin Meeser over 7 yearsThat is a one time producer - consumer, IMHO that is not really a producer - consumer pattern.