Global static initialization threading

c++, c++11

Solution

Is there any guarantee that global static initialization will be single threaded?

You mean dynamic initialization. No, single threaded initialization is explicitly not guaranteed.

From 3.6.2:

If a program starts a thread (30.3), the subsequent initialization of a variable is unsequenced with respect to the initialization of a variable defined in a different translation unit. Otherwise, the initialization of a variable is indeterminately sequenced with respect to the initialization of a variable defined in a different translation unit. If a program starts a thread, the subsequent unordered initialization of a variable is unsequenced with respect to every other dynamic initialization. Otherwise, the unordered initialization of a variable is indeterminately sequenced with respect to every other dynamic initialization

So if you start a thread in your program then two different global variables from two different TUs could theoretically have their constructors running at the same time from two different threads.

The best way to deal with these issues is to wrap your static storage duration variables as local static variables in the following "singleton pattern":

const T& f()
{
    static T t(a,b,c);
    return t;
}

The latest standard guarantees that the construction of `t` is thread-safe, so you will not need a mutex at all (at least not one explicitly specified, the compiler will generate the guard for you).

As an added benefit, the object is constructed "lazily" on the first call to `f`, so you don't need to worry about initialization order. If multiple such singletons call each other in their constructors (provided the dependencies are acyclic of course), they will be initialized in a working order. This is not the case for non-local variables.

Problem

I have a collection that I am protecting with a mutex. After initialization it is only ever read, so I won't need a mutex there. The collection is initialized and populated in global static initializers. I know that global static initialization is guaranteed within a single translation unit. Is there any guarantee that global static initialization will be single threaded? I have a static collection that protected by a Schwarz counter and is populated by constructors of other static objects. The container is associated with a mutex. Given that the collection is read-only after `main` starts, I would like to get rid of the mutex if I can guarantee that static constructors are called in a single thread. My understanding is that static initialization order is generally well defined within a single translation unit, but unspecified between translation units. Does the standard allow for the static objects to be initialized/constructed by different runtime provided threads? Schwarz counter: Header file: ``` struct Init { Init(); ~Init(); }; namespace { Init _init; } extern std::map<int, std::unique_ptr<...>> &protected; ``` Source file: ``` namespace { int init_count; std::aligned_storage<sizeof(std::map<int, std::unique_ptr<...>>), alignof(std::map<int, std::unique_ptr<...>>>)> protected_storage; } std::map<int, std::uniqe_ptr<...>> &protected = *reinterpret_cast<std::map<int, std::unique_ptr<...>> *>(&protected_storage); Init::Init() { if (!init_counter++) { new(&protected_storage) std::map<int, std::unique_ptr<...>>(); } } Init::~Init() { if (!--init_counter) { protected.~std::map<int, std::unique_ptr<...>>(); } } ``` Collection population: ``` struct helper { helper(...) { protected.insert(std::make_pair(...)); } }; ``` A macro is expanded that creates static instances of helper.

Original source