Proposed resolution:
Change [thread.once.callonce] p.2+3 as indicated:
template<class Callable, class ...Args> void call_once(once_flag& flag, Callable&& func, Args&&... args);[..]
2 Effects:
Calls to call_once on the same once_flag object are serialized. If there has been a prior effective call to call_once on the same once_flag object, the call to call_once returns without invoking func. If there has been no prior effective call to call_once on the same once_flag object, INVOKE(decay_copy( std::forward<Callable>(func)), decay_copy(std::forward<Args>(args))...) is executed. The call to call_once is effective if and only if INVOKE(decay_copy( std::forward<Callable>(func)), decay_copy(std::forward<Args>(args))...) returns without throwing an exception. If an exception is thrown it is propagated to the caller.An execution ofcall_once
that does not call itsfunc
is a passive execution. An execution ofcall_once
that calls itsfunc
is an active execution. An active execution shall callINVOKE(decay_copy(std::forward<Callable>(func)), decay_copy(std::forward<Args>(args))...)
. If such a call tofunc
throws an exception, the execution is exceptional, otherwise it is returning. An exceptional execution shall propagate the exception to the caller ofcall_once
. Among all executions ofcall_once
for any givenonce_flag
: at most one shall be a returning execution; if there is a returning execution, it shall be the last active execution; and there are passive executions only if there is a returning execution. [Note: Passive executions allow other threads to reliably observe the results produced by the earlier returning execution. — end note]3 Synchronization:
The completion of an effective call to call_once on a once_flag object synchronizes with ([intro.multithread]) all subsequent calls to call_once on the same once_flag object.For any givenonce_flag
: all active executions occur in a total order; completion of an active execution synchronizes with ([intro.multithread]) the start of the next one in this total order; and the returning execution synchronizes with the return from all passive executions.