[thread.once.callonce] (original) (raw)
32 Thread support library [thread]
32.5 Mutual exclusion [thread.mutex]
32.5.6 Call once [thread.once]
32.5.6.2 Function call_once [thread.once.callonce]
template<class Callable, class... Args> void call_once(once_flag& flag, Callable&& func, Args&&... args);
Mandates: is_invocable_v<Callable, Args...> is true.
Effects:An execution of call_once that does not call its func is apassive execution.
An execution of call_once that calls its funcis an active execution.
An active execution callsINVOKE(std::forward<Callable>(func), std::forward<Args>(args)...).
If such a call to functhrows an exception the execution is exceptional, otherwise it is returning.
An exceptional execution propagates the exception to the caller ofcall_once.
Among all executions of call_once for any givenonce_flag: at most one is a returning execution; if there is a returning execution, it is 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
]
Synchronization:For any given once_flag: all active executions occur in a total order; completion of an active execution synchronizes withthe start of the next one in this total order; and the returning execution synchronizes with the return from all passive executions.
[ Example
:
// global flag, regular function void init(); std::once_flag flag;
void f() { std::call_once(flag, init); }
// function static flag, function object struct initializer { void operator()(); };
void g() { static std::once_flag flag2; std::call_once(flag2, initializer()); }
// object flag, member function class information { std::once_flag verified; void verifier(); public: void verify() { std::call_once(verified, &information::verifier, *this); } };
— end example
]