While working with the threaded model of C++11, I noticed that
std::packaged_task<int(int,int)> task([](int a, int b) { return a + b; });
auto f = task.get_future();
task(2,3);
std::cout << f.get() << '\n';
and
auto f = std::async(std::launch::async,
[](int a, int b) { return a + b; }, 2, 3);
std::cout << f.get() << '\n';
seem to do exactly the same thing. I understand that there could be a major difference if I ran std::async
with std::launch::deferred
, but is there one in this case?
What is the difference between these two approaches, and more importantly, in what use cases should I use one over the other?
Actually the example you just gave shows the differences if you use a rather long function, such as
Packaged task
A
packaged_task
won't start on its own, you have to invoke it:std::async
On the other hand,
std::async
withlaunch::async
will try to run the task in a different thread:Drawback
But before you try to use
async
for everything, keep in mind that the returned future has a special shared state, which demands thatfuture::~future
blocks:So if you want real asynchronous you need to keep the returned
future
, or if you don't care for the result if the circumstances change:For more information on this, see Herb Sutter's article
async
and~future
, which describes the problem, and Scott Meyer'sstd::futures
fromstd::async
aren't special, which describes the insights. Also do note that this behavior was specified in C++14 and up, but also commonly implemented in C++11.Further differences
By using
std::async
you cannot run your task on a specific thread anymore, wherestd::packaged_task
can be moved to other threads.Also, a
packaged_task
needs to be invoked before you callf.get()
, otherwise you program will freeze as the future will never become ready:TL;DR
Use
std::async
if you want some things done and don't really care when they're done, andstd::packaged_task
if you want to wrap up things in order to move them to other threads or call them later. Or, to quote Christian: