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.