110 lines
4.5 KiB
Markdown
110 lines
4.5 KiB
Markdown
[thread.once]
|
||
|
||
# 32 Concurrency support library [[thread]](./#thread)
|
||
|
||
## 32.6 Mutual exclusion [[thread.mutex]](thread.mutex#thread.once)
|
||
|
||
### 32.6.7 Call once [thread.once]
|
||
|
||
#### [32.6.7.1](#onceflag) Struct once_flag [[thread.once.onceflag]](thread.once.onceflag)
|
||
|
||
[ð](#lib:once_flag)
|
||
|
||
namespace std {struct once_flag {constexpr once_flag() noexcept;
|
||
|
||
once_flag(const once_flag&) = delete;
|
||
once_flag& operator=(const once_flag&) = delete; };}
|
||
|
||
[1](#onceflag-1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L9379)
|
||
|
||
The class once_flag is an opaque data structure that call_once uses to
|
||
initialize data without causing a data race or deadlock[.](#onceflag-1.sentence-1)
|
||
|
||
[ð](#lib:once_flag_)
|
||
|
||
`constexpr once_flag() noexcept;
|
||
`
|
||
|
||
[2](#onceflag-2)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L9389)
|
||
|
||
*Synchronization*: The construction of a once_flag object is not synchronized[.](#onceflag-2.sentence-1)
|
||
|
||
[3](#onceflag-3)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L9393)
|
||
|
||
*Postconditions*: The object's internal state is set to indicate to an invocation ofcall_once with the object as its initial argument that no function has been
|
||
called[.](#onceflag-3.sentence-1)
|
||
|
||
#### [32.6.7.2](#callonce) Function call_once [[thread.once.callonce]](thread.once.callonce)
|
||
|
||
[ð](#lib:call_once)
|
||
|
||
`template<class Callable, class... Args>
|
||
void call_once(once_flag& flag, Callable&& func, Args&&... args);
|
||
`
|
||
|
||
[1](#callonce-1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L9409)
|
||
|
||
*Mandates*: is_invocable_v<Callable, Args...> is true[.](#callonce-1.sentence-1)
|
||
|
||
[2](#callonce-2)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L9413)
|
||
|
||
*Effects*: An execution of call_once that does not call its func is a[*passive*](#def:passive) execution[.](#callonce-2.sentence-1)
|
||
|
||
An execution of call_once that calls its func is an [*active*](#def:active) execution[.](#callonce-2.sentence-2)
|
||
|
||
An active execution evaluates*INVOKE*(std::forward<Callable>(func),
|
||
std::forward<Args>(args)...) ([[func.require]](func.require "22.10.4 Requirements"))[.](#callonce-2.sentence-3)
|
||
|
||
If such a call to func throws an exception the execution is [*exceptional*](#def:exceptional), otherwise it is [*returning*](#def:returning)[.](#callonce-2.sentence-4)
|
||
|
||
An exceptional execution propagates the exception to the caller ofcall_once[.](#callonce-2.sentence-5)
|
||
|
||
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[.](#callonce-2.sentence-6)
|
||
|
||
[*Note [1](#callonce-note-1)*:
|
||
|
||
Passive
|
||
executions allow other threads to reliably observe the results produced by the
|
||
earlier returning execution[.](#callonce-2.sentence-7)
|
||
|
||
â *end note*]
|
||
|
||
[3](#callonce-3)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L9433)
|
||
|
||
*Synchronization*: For any given once_flag: all active executions occur in a total
|
||
order; completion of an active execution [synchronizes with](intro.multithread#def:synchronize_with "6.10.2 Multi-threaded executions and data races [intro.multithread]") the start of the next one in this total order; and the returning execution
|
||
synchronizes with the return from all passive executions[.](#callonce-3.sentence-1)
|
||
|
||
[4](#callonce-4)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L9440)
|
||
|
||
*Throws*: system_error when
|
||
an exception is required ([[thread.req.exception]](thread.req.exception "32.2.2 Exceptions")), or any exception thrown by func[.](#callonce-4.sentence-1)
|
||
|
||
[5](#callonce-5)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L9445)
|
||
|
||
[*Example [1](#callonce-example-1)*: // global flag, regular functionvoid init();
|
||
std::once_flag flag;
|
||
|
||
void f() { std::call_once(flag, init);}// function static flag, function objectstruct initializer {void operator()();};
|
||
|
||
void g() {static std::once_flag flag2;
|
||
std::call_once(flag2, initializer());}// object flag, member functionclass information { std::once_flag verified; void verifier();public:void verify() { std::call_once(verified, &information::verifier, *this); }}; â *end example*]
|