std::async won't spawn a new thread when return value is not stored

房东的猫 提交于 2020-07-09 06:45:12

问题


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?


回答1:


From just::thread documentation:

If policy is std::launch::async then runs INVOKE(fff,xyz...) on its own thread. The returned std::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 returned std::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.




回答2:


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.




回答3:


Why blocking?

  1. std::async(); returns std::future temporary object
  2. temporary object is destroyed immediately, calling desctructor.
  3. 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.



来源:https://stackoverflow.com/questions/62312315/c-stdasync-is-being-called-synchronously-when-inside-a-switch-statement

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!