I am having a hard time understanding why following code blocks:
{
std::async(std::launch::async, [] { std::this_thread::sleep_for(5s);
// this line will not execute until above task finishes?
}
I suspect that std::async
returns std::future
as temporary which in destructor joins on the task thread. Is it possible?
Full code is below:
int main() {
using namespace std::literals;
{
auto fut1 = std::async(std::launch::async, [] { std::this_thread::sleep_for(5s); std::cout << "work done 1!\n"; });
// here fut1 in its destructor will force a join on a thread associated with above task.
}
std::cout << "Work done - implicit join on fut1 associated thread just ended\n\n";
std::cout << "Test 2 start" << std::endl;
{
std::async(std::launch::async, [] { std::this_thread::sleep_for(5s); std::cout << "work done 2!" << std::endl; });
// no future so it should not join - but - it does join somehow.
}
std::cout << "This shold show before work done 2!?" << std::endl;
}
Yes,
std::future
returned byasync
has the special property of waiting for the task to be completed in the destructor.This is because loose threads are bad news, and the only token you have to wait for that thread is in the destructor of the future.
To fix this, store the resulting futures until either you need the result to be done, or in extreme cases the end of the program.
Writing your own thread pool system is also a good idea; I find C++ threading primitives to be sufficient to write a threading system, but use in the raw is not something I'd encourage outside of tiny programs.