Skip to content

Clarify std::async policy behavior #5053

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jun 27, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/standard-library/future-functions.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ The second function returns a `future<Ty>` object whose *associated asynchronous

Unless `decay<Fn>::type` is a type other than launch, the second function doesn't participate in overload resolution.

The C++ standard states that if policy is launch::async, the function creates a new thread. However the Microsoft implementation is currently non-conforming. It obtains its threads from the Windows ThreadPool, which in some cases may provide a recycled thread rather than a new one. This means that the `launch::async` policy is implemented as `launch::async|launch::deferred`. Another implication of the ThreadPool-based implementation is that there's no guarantee that thread-local variables will be destroyed when the thread completes. If the thread is recycled and provided to a new call to `async`, the old variables will still exist. We recommend that you don't use thread-local variables with `async`.
The C++ standard states that if the policy is `launch::async`, the function behaves as if it invokes the callable object in a new thread. This means that while it typically results in creating a new thread, the implementation may use other mechanisms to achieve equivalent behavior. However, the Microsoft implementation currently does not conform strictly to this behavior. It obtains its threads from the Windows ThreadPool, which may provide a recycled thread rather than a new one. This means that the `launch::async` policy is effectively implemented as `launch::async|launch::deferred`. Another implication of the ThreadPool-based implementation is that there's no guarantee that thread-local variables will be destroyed when the thread completes. If the thread is recycled and provided to a new call to `async`, the old variables will still exist. We recommend that you avoid using thread-local variables with `async`.

If *policy* is `launch::deferred`, the function marks its associated asynchronous state as holding a *deferred function* and returns. The first call to any non-timed function that waits for the associated asynchronous state to be ready in effect calls the deferred function by evaluating `INVOKE(dfn, dargs..., Ty)`.

Expand Down