2 Answers
2

A launch policy of std::launch::async | std::launch::deferred means that the implementation can choose whether to apply a policy of std::launch::async or std::launch::deferred. This choice may vary from call to call, and may not be decided immediately.

An implementation that always chooses one or the other is thus legal (which is what gcc does, always choosing deferred), as is one that chooses std::launch::async until some limit is reached, and then switches to std::launch::deferred.

It also means that the implementation can defer the choice until later. This means that the implementation may wait to make a decision until its hand is forced by a call that has visibly distinct effects from deferred and async tasks, or until the number of running tasks is less than the internal task limit. This is what just::thread does.

The functions that force the decision are: wait(), get(), wait_for(), wait_until(), and the destructor of the last future object referencing the result.

Chaprer 30.6.8 of ISO IEC 14882-2011 explains that launch::async | launch::deferred means implementations should defer invocation or the selection of the policy when no more concurrency can be effectively exploited (same as async without policy parameter).

In practice it means that C++ runtime should start new threads for each async as long as there are unused CPU cores.

Found the followig quote which made it clearer for me: "it is up to the implementation whether to perform asynchronous execution or lazy evaluation."
– ronagFeb 20 '12 at 11:39

1

So a std::async call without any arguments does not in any way guarantee that it will actually executed. That is a bit of a gotcha, in the case of "fire-and-forget".
– ronagFeb 20 '12 at 12:03

1

Actually, you can get some sort of "fire-and-forget" with RAII. Just guarantee that get would be called in the destructor of some object, containing the future.
– Evgeny KluevFeb 20 '12 at 12:19

2

The behavior of terminate is to simply interrupt the thread. But I was mistaken about future's implementation. It joins the thread before destructing it. So future's destructor will just wait for thread's completion. No problem here.
– Evgeny KluevFeb 20 '12 at 13:01