Fixed a static initialization race.

This commit is contained in:
Matthias Köfferlein 2018-09-09 18:31:05 +02:00
parent 940a96716c
commit e69ed872a7
1 changed files with 21 additions and 8 deletions

View File

@ -49,7 +49,8 @@ namespace {
// TODO: thread-safe? Unlikely that multiple threads access this member -
// we do a initial scan and after this no more write access here.
static std::map<const std::type_info *, const ClassBase *, type_info_compare> s_ti_to_class;
typedef std::map<const std::type_info *, const ClassBase *, type_info_compare> ti_to_class_map_t;
static ti_to_class_map_t *sp_ti_to_class = 0;
ClassBase::ClassBase (const std::string &doc, const Methods &mm, bool do_register)
: m_initialized (false), mp_base (0), mp_parent (0), m_doc (doc), m_methods (mm)
@ -63,7 +64,10 @@ ClassBase::ClassBase (const std::string &doc, const Methods &mm, bool do_registe
mp_new_class_collection->push_back (this);
// invalidate the "typeinfo to class" map
s_ti_to_class.clear ();
if (sp_ti_to_class) {
delete sp_ti_to_class;
sp_ti_to_class = 0;
}
}
}
@ -625,7 +629,12 @@ static void add_class_to_map (const gsi::ClassBase *c)
if (! ti) {
ti = &c->type ();
}
if (ti && c->is_of_type (*ti) && !s_ti_to_class.insert (std::make_pair (ti, c)).second) {
if (! sp_ti_to_class) {
sp_ti_to_class = new ti_to_class_map_t ();
}
if (ti && c->is_of_type (*ti) && !sp_ti_to_class->insert (std::make_pair (ti, c)).second) {
// Duplicate registration of this class
tl::error << "Duplicate registration of class " << c->name () << " (type " << ti->name () << ")";
tl_assert (false);
@ -634,7 +643,7 @@ static void add_class_to_map (const gsi::ClassBase *c)
const ClassBase *class_by_typeinfo_no_assert (const std::type_info &ti)
{
if (s_ti_to_class.empty ()) {
if (! sp_ti_to_class || sp_ti_to_class->empty ()) {
for (gsi::ClassBase::class_iterator c = gsi::ClassBase::begin_classes (); c != gsi::ClassBase::end_classes (); ++c) {
add_class_to_map (c.operator-> ());
}
@ -643,11 +652,15 @@ const ClassBase *class_by_typeinfo_no_assert (const std::type_info &ti)
}
}
std::map<const std::type_info *, const ClassBase *, type_info_compare>::const_iterator c = s_ti_to_class.find (&ti);
if (c != s_ti_to_class.end ()) {
return c->second;
} else {
if (! sp_ti_to_class) {
return 0;
} else {
std::map<const std::type_info *, const ClassBase *, type_info_compare>::const_iterator c = sp_ti_to_class->find (&ti);
if (c != sp_ti_to_class->end ()) {
return c->second;
} else {
return 0;
}
}
}