This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of C++11 status.

### 1494. Term "are serialized" not defined

Section: 33.6.7.2 [thread.once.callonce] Status: C++11 Submitter: INCITS Opened: 2010-08-25 Last modified: 2016-01-28

Priority: Not Prioritized

View all other issues in [thread.once.callonce].

View all issues with C++11 status.

Discussion:

Addresses US-190

The term "are serialized" is never defined (33.6.7.2 [thread.once.callonce] p. 2).

[ Resolution proposed by ballot comment: ]

Remove the sentence with "are serialized" from paragraph 2. Add "Calls to `call_once` on the same `once_flag` object shall not introduce data races (17.6.4.8)." to paragraph 3.

[ 2010-11-01 Daniel translates NB comment into wording ]

[ 2011-02-17: Hans proposes an alternative resolution ]

[ 2011-02-25: Hans, Clark, and Lawrence update the suggested wording ]

[2011-02-26 Reflector discussion]

Moved to Tentatively Ready after 5 votes.

Proposed resolution:

Change 33.6.7.2 [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 of `call_once` that does not call its `func` is a passive execution. An execution of `call_once` that calls its `func` is an active execution. An active execution shall call `INVOKE(decay_copy(std::forward<Callable>(func)), decay_copy(std::forward<Args>(args))...)`. If such a call to `func` throws an exception, the execution is exceptional, otherwise it is returning. An exceptional execution shall propagate the exception to the caller of `call_once`. Among all executions of `call_once` for any given `once_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 (6.9.2 [intro.multithread]) all subsequent calls to `call_once` on the same `once_flag` object.For any given `once_flag`: all active executions occur in a total order; completion of an active execution synchronizes with (6.9.2 [intro.multithread]) the start of the next one in this total order; and the returning execution synchronizes with the return from all passive executions.