I have multiple global object (say, Duck, Dog, Cat) which has to be global object, and they have a common parent class Animal.
I try to use registry pattern in such way:
- declare all of these instances in global object in
.cc
file, likeCat cat("cat");
- The ctor of all derived animals are empty, so it directly delegates to parent class's ctor. In the ctor of
Animal
, it register itself into a single registry byAnimalRegistry::GetInstance().Register(this);
AnimalRegistry
maintains a "animal-type -> animal instance*" mapping
When I'm using thread-sanitizer, I meet an issue:
ThreadSanitizer: data race on vptr (ctor/dtor vs virtual call)
After some searching, I think the problem could be: https://github.com/google/sanitizers/wiki/ThreadSanitizerPopularDataRaces#data-race-on-vptr-during-construction
Since these registration happens in constructor, and at this time the objects are partially constructed.
My question is: how could I achieve global objects registration?
The problem here is that you declared all instances "... in
.cc
file, likeCat cat("cat");
", as you write above.This looks okay at first glance, but consider this: Another (global) static variable starts a thread and this thread is accessing your global objects, possibly before they have been constructed.
If you can be sure that this will not happen, you can ignore it. Otherwise look at
std::call_once
and includestd::call_once
construct to all calls using your registry objects. This will make sure that regardless of what thread is using the registry object, the objects will have been constructed and their constructors will have been called exactly once.