Modern Effective C++ - Use launch policy std::launch::async to force asynchronicity.

As already discussed in the previous article, when std::async is started without launch policy, a default launch policy is used, which at runtime determines if it's best to create a thread or not.

There are two launch policies in std::async. They are -
  1. std::launch::async -  Async creates a new thread.
  2. std::launch::deferred - The async function is not called until a wait / get is called on the future of the async function. Thus the function is executed synchronously in the same thread.

Note that the launch policy is a scoped enum.




When the caller does not supply a launch policy, a default launch policy of std::launch::async | std::launch::deferred is used.

Hence when we use the default policy, the function supplied to async can run synchronously or asynchronously.

But there are certain issues when we do not supply the launch policy i.e use the default launch policy -
  1. Not sure if the code will run concurrently or not.
  2. Unable to predict if a new thread will be created if wait or get is called.
  3. The function may not be called at all - if the code doesn't take the exit path, which has wait or get.

A particular bug can occur when we run std::async with std::launch::deferred or the default launch policy, as seen in the below program.


If you run this program, you will notice that it goes into a infinite loop. This is because the future status will always be std::future_status::deferred and will never become std::future_status::ready. This incorrect behavior is quite evident with the std::launch::deferred launch policy, and might turn out to be a insidious bug when the default launch policy is used. This is because when the default launch policy is used, it is decided at runtime whether to create a new thread or not. During testing, usually the system is under low load, and new thread is spawned and the program seems to work as expected. However when the code is in production, under heavy load, the default policy might decide to run this async function as deferred i.e in the current thread. But the code is busy executing the wait_for loop and it never yields the control to the async function.

The correct way of using wait_for / wait_until for a thread with default launch policy is demonstrated below. This program does not go into infinite loop -


On the ending note, std::future_status is an enum class and the values of the members are demonstrated in the program below.



This article was inspired by Effective Modern C++ by Scott Meyers. I highly recommend you guys to check it out.


Modern Effective C++ - Use launch policy std::launch::async to force asynchronicity. Modern Effective C++ - Use launch policy std::launch::async to force asynchronicity. Reviewed by zeroingTheDot on May 09, 2018 Rating: 5

No comments:

Powered by Blogger.