Kerrek SB is correct with his answer, but I suggested to add another example (which he suggested should be an answer, so here it is).
I discovered recently that at least in VC11, std::async
will not release all the resources of the thread until the end of the application, making possible to get memory leak false positive (if you are monitoring them using, for example Visual Leak Detector).
Here I mean that in most basic applications it is not worth looking at the rest of this answer, but if like me you need to check memory leaks and can't afford to let false positive, like static data not released at the end of the main function. If it's your case, then this might help.
std::async
is not guaranteed to run in a separate thread by default, it is only if you use std::launch::async
as first parameter. Otherwise the implementation decide what to do, and that's why VC11 implementation will use the new Microsoft Concurrency Runtime task manager to manage the provided function as a task pushed in a task pool, which mean threads are maintained and managed in a transparent way. There are ways to explicitely terminate the task manager but that's too platform specific, making async a poor choice when you want exactly 1) be sure to launch a thread and 2) get a result later and 3) be sure the thread is fully released when you get the result.
The alternative that does exactly that is to use std::packaged_task
and std::thread
in combination with std::future
. The way it is done is almost similar to using std::async
, just a bit more verbose (which mean you can generalize it in a custom template function if you want).
#include <packaged_task>
#include <thread>
int myfun(double, char, bool);
std::packaged_task<int(double, char, bool)> task(myfun, arg1, arg2, arg3);
auto f = task.get_future(); // f is a std::future<int>
First we create a task, basically an object containing both the function and the std::promise
that will be associated with the future. std::packaged_task
works mostly like an augmented version of std::function
:
Now we need to execute the thread explicitly:
std::thread thread(std::move(task));
thread.detach();
The move is necessary because std::packaged_task
is not copyable. Detaching the thread is only necessary if you only want to synchronize using the future – otherwise you will need to join the thread explicitly. If you don't, when thread's destructor is called, it will just call std::terminate()
.
// ...
int res = f.get(); // Synchronization and retrieval.