30 Thread support library [thread]

30.4 Mutual exclusion [thread.mutex]

30.4.4 Call once [thread.once]

The class once_flag is an opaque data structure that call_once uses to initialize data without causing a data race or deadlock.

30.4.4.1 Struct once_flag [thread.once.onceflag]

constexpr once_flag() noexcept;

Effects: Constructs an object of type once_flag.

Synchronization: The construction of a once_flag object is not synchronized.

Postcondition: The object's internal state is set to indicate to an invocation of call_once with the object as its initial argument that no function has been called.

30.4.4.2 Function call_once [thread.once.callonce]

template<class Callable, class ...Args> void call_once(once_flag& flag, Callable&& func, Args&&... args);

Requires: Callable and each Ti in Args shall satisfy the MoveConstructible requirements. INVOKE(DECAY_COPY( std::forward<Callable>(func)), DECAY_COPY(std::forward<Args>(args))...) ([func.require]) shall be a valid expression.

Effects: 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 ]

Synchronization: For any given once_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.

Throws: system_error when an exception is required ([thread.req.exception]), or any exception thrown by func.

Error conditions:

  • invalid_argument — if the once_flag object is no longer valid.

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 ]