DelayedInit ‐‐ thread‐safe delayed initialization of a value. There are two important differences between Lazy and DelayedInit: 1. DelayedInit does not store the factory function inline. 2. DelayedInit is thread‐safe.
Synopsis
Declared in <folly/synchronization/DelayedInit.h>
template<typename T>
struct DelayedInit;
Description
Due to these differences, DelayedInit is suitable for data members. Lazy is best for local stack variables.
Example Usage:
struct Foo { Bar& bar() { LargeState state; return bar_.try_emplace_with( [this, &state]{ return computeBar(state); }); } private: Bar computeBar(LargeState&); DelayedInit<Bar> bar_; };
If the above example were to use Lazy instead of DelayedInit:
-
Storage for LargeState and this‐pointer would need to be reserved in the struct which wastes memory.
-
It would require additional synchronization logic for thread‐safety.
Rationale:
-
The stored value is initialized at most once and never deinitialized. Unlike Lazy, the initialization logic must be provided by the consumer. This means that DelayedInit is more of a "storage" type like std::optional. These semantics are perfect for thread‐safe, lazy initialization of a data member.
-
DelayedInit models neither MoveConstructible nor CopyConstructible. The rationale is the same as that of std::once_flag.
-
There is no need for a non‐thread‐safe version of DelayedInit. std::optional will suffice in these cases.
Member Functions
Name |
Description |
|
Constructors |
|
Deleted copy assignment; DelayedInit is not copyable. |
Checks whether the value has been initialized. |
|
Returns the stored value without checking for initialization. |
|
Accesses members of the stored value. |
|
|
|
Gets the pre‐existing value if already initialized or creates the value returned by the provided factory function. If the value already exists, then the provided function is not called. |
|
Returns the stored value, throwing if it is not initialized. |
|
Checks whether the value has been initialized. |
Created with MrDocs