`std::once_flag` holds synchronization data for one initialization; use a separate flag for each. Pass it and an initialization callable to `std::call_once`. When that call returns, initialization is complete in a properly synchronized fashion, so callers can use the object. This avoids unsafe pointer checks that can cause a data race. Compared with an explicit mutex, this approach typically has lower overhead, especially after initialization. section 3.3.1
std::shared_ptr<some_resource> resource_ptr;
std::once_flag resource_flag; #1
void init_resource()
{
resource_ptr.reset(new some_resource);
}
void foo()
{
std::call_once(resource_flag,init_resource); #2
resource_ptr->do_something();
}
A flag and callable initialize a shared resource once before it is used. section 3.3.1
Listing 3.12. Thread-safe lazy initialization of a class member using std::call_once
class X
{
private:
connection_info connection_details;
connection_handle connection;
std::once_flag connection_init_flag;
void open_connection()
{
connection=connection_manager.open(connection_details);
}
public:
X(connection_info const& connection_details_):
connection_details(connection_details_)
{}
void send_data(data_packet const& data) #1
{
std::call_once(connection_init_flag,&X::open_connection,this); #2
connection.send_data(data);
}
data_packet receive_data() #3
{
std::call_once(connection_init_flag,&X::open_connection,this); #2
return connection.receive_data();
}
};
!@%STYLE%@!
{"css":"{\"css\": \"font-weight: bold;\"}","target":"[[{\"line\":14,\"ch\":72},{\"line\":14,\"ch\":74}],[{\"line\":16,\"ch\":72},{\"line\":16,\"ch\":74}],[{\"line\":21,\"ch\":72},{\"line\":21,\"ch\":74}],[{\"line\":19,\"ch\":72},{\"line\":19,\"ch\":74}],[{\"line\":16,\"ch\":72},{\"line\":16,\"ch\":74}],[{\"line\":21,\"ch\":72},{\"line\":21,\"ch\":74}]]"}
!@%STYLE%@!
A class member flag lets either send_data or receive_data trigger connection initialization. section 3.3.1
