Reputation: 34608
Consider I have lamba foo
which just does some stuff and doesn't need to return anything.
When I do this:
std::future<T> handle = std::async(std::launch::async, foo, arg1, arg2);
Everything runs fine and the lamba will be spawned in a new thread.
However, when I don't store the std::future
which the std::async
returns, the foo will be run in the main thread and block it.
std::async(std::launch::async, foo, arg1, arg2);
What am I missing here?
Upvotes: 18
Views: 4805
Reputation: 691
Why blocking?
std::async();
returnsstd::future
temporary object- temporary object is destroyed immediately, calling desctructor.
std::future
destructor is blocking. It is bad and troublesome.
Why assigning is ok?
By assigning to a variable, the returned object is not destroyed immediately, but later, until end of scope of your calling code.
Code Example: main1
is ok. main2
and main3
are equivalently blocking the main thread.
void forever() {
while (true);
}
void main1() {
std::future<void> p = std::async(std::launch::async, forever);
std::cout << "printing" << std::endl; // can print, then forever blocking
}
void main2() {
std::async(std::launch::async, forever);
std::cout << "printing" << std::endl; // forever blocking first, cannot print
}
void main3() {
{std::future<void> p = std::async(std::launch::async, forever);}
std::cout << "printing" << std::endl; // forever blocking first, cannot print
}
Take a look at cplusplus.com
Return value of std::async When launch::async is selected, the future returned is linked to the end of the thread created, even if its shared state is never accessed: in this case, its destructor synchronizes with the return of fn. Therefore, the return value shall not be disregarded for asynchronous behavior, even when fn returns void.
Upvotes: 3
Reputation: 810
From just::thread
documentation:
If policy is
std::launch::async
then runsINVOKE(fff,xyz...)
on its own thread. The returnedstd::future
will become ready when this thread is complete, and will hold either the return value or exception thrown by the function invocation. The destructor of the last future object associated with the asynchronous state of the returnedstd::future
shall block until the future is ready.
In
std::async(std::launch::async, foo, arg1, arg2);
The returned future is not assigned anywhere and its destructor blocks until foo
finishes.
Upvotes: 20
Reputation: 20853
I would like to add a link to an article by Herb Sutter on async and ~future in which he argues that futures should never block.
Upvotes: 6