This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of New status.
std::async exceptions are handledSection: 32.10.9 [futures.async] Status: New Submitter: Jonathan Wakely Opened: 2021-08-23 Last modified: 2021-09-30
Priority: 3
View other active issues in [futures.async].
View all other issues in [futures.async].
View all issues with New status.
Discussion:
32.10.9 [futures.async] (3.1) says:
Any exception propagated from the execution of
invoke(decay-copy(std::forward<F>(f)), decay-copy(std::forward<Args>(args))...)is stored as the exceptional result in the shared state.
It's not clear whether this includes the evaluation of the decay-copy calls in the calling
thread, or only the invocation of invoke with the results of those decay-copy calls.
invoke, not the
calls to decay-copy. Exceptions from the decay-copy calls are propagated
to the caller of std::async. We should clarify that that's what the standard means.
[2021-09-20; Reflector poll]
Set priority to 3 after reflector poll.
[2021-09-20; Jonathan updates wording to change the Throws: and attempt to align the Effects: with the deferred function case. ]
Previous resolution [SUPERSEDED]:
This wording is relative to N4892.
Modify 32.10.9 [futures.async] as indicated:
template<class F, class... Args> [[nodiscard]] future<invoke_result_t<decay_t<F>, decay_t<Args>...>> async(F&& f, Args&&... args); template<class F, class... Args> [[nodiscard]] future<invoke_result_t<decay_t<F>, decay_t<Args>...>> async(launch policy, F&& f, Args&&... args);-2- Mandates: […]
-3- Effects: The first function behaves the same as a call to the second function with apolicyargument oflaunch::async | launch::deferredand the same arguments forFandArgs. The second function creates a shared state that is associated with the returnedfutureobject. The further behavior of the second function depends on thepolicyargument as follows (if more than one of these conditions applies, the implementation may choose any of the corresponding policies):
(3.1) — If
launch::asyncis set inpolicy, callsinvoke(decay-copy(std::forward<F>(f)), decay-copy(std::forward<Args>(args))...)(22.10.4 [func.require], 32.4.3.3 [thread.thread.constr]) as if in a new thread of execution represented by athreadobject with the calls todecay-copybeing evaluated in the thread that calledasync. Any return value is stored as the result in the shared state. Any exception propagated from theexecution ofcall toinvoke(decay-copy(std::forward<F>(f)), decay-copy(std::forward<Args>(args))...)invokeis stored as the exceptional result in the shared state. [Note ?: Exceptions from thedecay-copycalls are propagated to the caller. — end note] Thethreadobject is stored in the shared state and affects the behavior of any asynchronous return objects that reference that state.[…]
Proposed resolution:
This wording is relative to N4892.
Modify 32.10.9 [futures.async] as indicated:
template<class F, class... Args> [[nodiscard]] future<invoke_result_t<decay_t<F>, decay_t<Args>...>> async(F&& f, Args&&... args); template<class F, class... Args> [[nodiscard]] future<invoke_result_t<decay_t<F>, decay_t<Args>...>> async(launch policy, F&& f, Args&&... args);-2- Mandates: […]
-3- Effects: The first function behaves the same as a call to the second function with apolicyargument oflaunch::async | launch::deferredand the same arguments forFandArgs. The second function creates a shared state that is associated with the returnedfutureobject. The further behavior of the second function depends on thepolicyargument as follows (if more than one of these conditions applies, the implementation may choose any of the corresponding policies):
(3.1) — If
launch::asyncis set inpolicy, callsinvoke(decay-copy(std::forward<F>(f)), decay-copy(std::forward<Args>(args))...)(22.10.4 [func.require], 32.4.3.3 [thread.thread.constr]) as if in a new thread of execution represented by athreadobject with the calls todecay-copybeing evaluated in the thread that calledasync. Any return value is stored as the result in the shared state. Any exception propagated from the execution ofinvoke(is stored as the exceptional result in the shared state, wheredecay-copy(std::forward<F>(f)), decay-copy(std::forward<Args>(args)...)std::move(g), std::move(xyz))gis the result ofdecay-copy(std::forward<F>(f))andxyzis the result ofdecay-copy(std::forward<Args>(args)).... [Note ?: Exceptions from thedecay-copycalls are propagated to the caller. — end note] Thethreadobject is stored in the shared state and affects the behavior of any asynchronous return objects that reference that state.[…]
[…]
-6- Throws:
system_errorifpolicy == launch::asyncand the implementation is unable to start a new thread;if memory for the internal data structures cannot be allocated; or any exception thrown by the initialization of the objects returned by thestd::bad_allocdecay-copycalls.