33 Thread support library [thread]

33.4 Mutual exclusion [thread.mutex]

33.4.6 Call once [thread.once]

33.4.6.1 Struct once_­flag [thread.once.onceflag]

namespace std {
  struct once_flag {
    constexpr once_flag() noexcept;

    once_flag(const once_flag&) = delete;
    once_flag& operator=(const once_flag&) = delete;
  };
}

The class once_­flag is an opaque data structure that call_­once uses to initialize data without causing a data race or deadlock.

constexpr once_flag() noexcept;

Effects: Constructs an object of type once_­flag.

Synchronization: The construction of a once_­flag object is not synchronized.

Postconditions: 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.

33.4.6.2 Function call_­once [thread.once.callonce]

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

Requires:

INVOKE(std::forward<Callable>(func), std::forward<Args>(args)...)

(see [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(​std​::​forward<Callable>(func), 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 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.

[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]