4

I don't get the reason behind using std::async with std::lauch::async flag, instead of simply calling the function passed to std::async. Are there any specials guarantees?

6
  • Are you actually asking about std::lauch::deferred? Because std::lauch::async behaves completely different from just calling the function, excuting it asynchronously in another thread (but maybe you're actually asking for the reasons to do so in the first place, which would be a much more fundamental question, though). Commented Nov 21, 2013 at 16:46
  • @LightnessRacesinOrbit I'm not sure your edit to the question title (along with your answer) really matches the question body. Commented Nov 21, 2013 at 16:49
  • @Christian Rau: In the the documentation it is specified that when we call std::async with std::lauch::async flag, the calling thread will block until func() completes, so I think my original question/title is fine Commented Nov 21, 2013 at 17:03
  • @ChristianRau: Oops, you're right. That also means my answer is not quite correct; fixing it now. Thanks! Commented Nov 21, 2013 at 17:08
  • 1
    @Guillaume07 That is in general not the case. You might be referring to the infamous behaviour of blocking if not assigning the resulting future to any variable (as stated in the "Notes" section of that documentation), in which case the destructor (that indeed blocks until the function finishes) is invoked right away. But this isn't the general use-case of std::async and if it's that special case you're after, you might want to clarify your question a bit. Commented Nov 21, 2013 at 17:15

2 Answers 2

4

According to the documentation, there is an overload that just takes the function and its arguments. You're using an overload that accepts a more specific policy.

async(f, args...) is equivalent to async(std::launch::async | std::launch::deferred, f, args...), where the presence of both flags leaves it up to the implementation as to whether the function is simply de-coupled from the current call stack (deferred to execution of the first non-timed wait function; this is called lazy evaluation), or actually multi-threaded.

The call you're using, by giving only std::launch::async, ensures that the function is definitely executed in its own thread, avoiding any work blocking the calling thread.

Both variants are still, of course, wholly dissimilar from simply invoking f(args...) directly, which guarantees immediate evaluation.

Sign up to request clarification or add additional context in comments.

8 Comments

The weird thing about std::launch::async | std::launch::deferred is that it gives the implementation not only the choice between async and deferred execution, but it also allows the implementation to defer making that choice. That is, the implementation might not choose either policy immediately, but sometime later might choose to do asynchronous execution (e.g., after another thread completes and a core becomes available). As far as I know Microsoft's implementation is the only one that takes advantage of this, and I believe they were responsible for putting this latitude into the spec.
@bames53: Shoot to kill!
@bames53 - that doesn't sound weird. It's just a consequence of the underlying abstraction: there's no way a portable program can determine when the runtime library decided which way to handle that parameter, so there's nothing there to specify.
@PeteBecker Actually it can be detected if the delay in making that policy decision is such that it creates a new dependency between tasks. Adding that dependency can create a circular dependency and produce a deadlock. VS2012 can be made to exhibit this behavior.
@PeteBecker "Isn't that also true of std::launch::async?" No, the scheduler would have to completely starve some threads for that to happen, which goes against 1.10/2. "And how does your program portably detect that that happened," The program operator detects it when a program that should complete fails to make progress. "how did deferring the decision [...] make a difference?" The implementation included implicit dependencies for the decision, resulting in circular dependencies that don't appear in the source and which prevent the program from completing.
|
1

Yes the calling thread does not block because std::async generates a separate thread to invoke the function. That means if you click on a GUI Button to start the processing of a complex task which will take several minutes then the GUI responses although the processing is not finished yet.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.