From 6ba372f1a9dc1d8cbe9fc46989f0a4b6829d9cde Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20K=C3=B6fferlein?= Date: Sun, 17 Jul 2022 19:59:49 +0200 Subject: [PATCH] Issue 1114 (#1121) * Two patches to enable building on MSYS with gcc 12.1 1. Complete explicit instantiations in dbHierProcessor 2. Strict weak ordering is not present for std::type_info (using "before" on gcc 12.1). We need to work with plain pointers and use a translation table to associate pointers with classes. * Fixed another place where std::type_info got important Co-authored-by: Matthias Koefferlein --- src/db/db/dbHierProcessor.cc | 7 +++ src/gsi/gsi/gsiClassBase.cc | 57 +++++++++++++++-------- src/tl/tl/tlVariant.cc | 88 +++++++++++++++++++++++++++++++----- 3 files changed, 122 insertions(+), 30 deletions(-) diff --git a/src/db/db/dbHierProcessor.cc b/src/db/db/dbHierProcessor.cc index 87ca8a900..a52f8bef2 100644 --- a/src/db/db/dbHierProcessor.cc +++ b/src/db/db/dbHierProcessor.cc @@ -1261,13 +1261,20 @@ template class DB_PUBLIC local_processor_context_computation_task; template class DB_PUBLIC local_processor_context_computation_task; template class DB_PUBLIC local_processor_context_computation_task; +template class DB_PUBLIC local_processor_context_computation_task; +template class DB_PUBLIC local_processor_context_computation_task; +template class DB_PUBLIC local_processor_context_computation_task; +template class DB_PUBLIC local_processor_context_computation_task; template class DB_PUBLIC local_processor_context_computation_task; +template class DB_PUBLIC local_processor_context_computation_task; +template class DB_PUBLIC local_processor_context_computation_task; template class DB_PUBLIC local_processor_context_computation_task; template class DB_PUBLIC local_processor_context_computation_task; template class DB_PUBLIC local_processor_context_computation_task; template class DB_PUBLIC local_processor_context_computation_task; template class DB_PUBLIC local_processor_context_computation_task; template class DB_PUBLIC local_processor_context_computation_task; +template class DB_PUBLIC local_processor_context_computation_task; // --------------------------------------------------------------------------------------------- // LocalProcessorResultComputationTask implementation diff --git a/src/gsi/gsi/gsiClassBase.cc b/src/gsi/gsi/gsiClassBase.cc index bcc8b66b0..524747ecf 100644 --- a/src/gsi/gsi/gsiClassBase.cc +++ b/src/gsi/gsi/gsiClassBase.cc @@ -49,9 +49,11 @@ namespace { // TODO: thread-safe? Unlikely that multiple threads access this member - // we do a initial scan and after this no more write access here. -typedef std::map ti_to_class_map_t; -static ti_to_class_map_t *sp_ti_to_class = 0; -// NOTE: MacOS/clang seems to have some issue with RTTI across shared objects. This map provides a name-based fallback +static std::vector *sp_classes = 0; +typedef std::map class_to_index_map_t; +static class_to_index_map_t *sp_class_to_index = 0; +typedef std::map ti_to_class_map_t; +static ti_to_class_map_t *sp_ti_to_class_index = 0; typedef std::map tname_to_class_map_t; static tname_to_class_map_t *sp_tname_to_class = 0; @@ -67,9 +69,17 @@ 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 - if (sp_ti_to_class) { - delete sp_ti_to_class; - sp_ti_to_class = 0; + if (sp_classes) { + delete sp_classes; + sp_classes = 0; + } + if (sp_class_to_index) { + delete sp_class_to_index; + sp_class_to_index = 0; + } + if (sp_ti_to_class_index) { + delete sp_ti_to_class_index; + sp_ti_to_class_index = 0; } if (sp_tname_to_class) { delete sp_tname_to_class; @@ -826,14 +836,25 @@ static void add_class_to_map (const gsi::ClassBase *c) ti = &c->type (); } - if (! sp_ti_to_class) { - sp_ti_to_class = new ti_to_class_map_t (); + if (! sp_classes) { + sp_classes = new std::vector (); + } + if (! sp_class_to_index) { + sp_class_to_index = new class_to_index_map_t (); + } + if (! sp_ti_to_class_index) { + sp_ti_to_class_index = new ti_to_class_map_t (); } if (! sp_tname_to_class) { sp_tname_to_class = new tname_to_class_map_t (); } - if (!sp_ti_to_class->insert (std::make_pair (ti, c)).second) { + auto c2i = sp_class_to_index->insert (std::make_pair (c, sp_classes->size ())).first; + if (c2i->second >= sp_classes->size ()) { + sp_classes->push_back (c); + } + + if (!sp_ti_to_class_index->insert (std::make_pair (ti, c2i->second)).second) { // Duplicate registration of this class tl::error << "Duplicate registration of class " << c->name () << " (type " << ti->name () << ")"; tl_assert (false); @@ -844,27 +865,27 @@ static void add_class_to_map (const gsi::ClassBase *c) const ClassBase *class_by_typeinfo_no_assert (const std::type_info &ti) { - 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) { + if (! sp_ti_to_class_index || sp_ti_to_class_index->empty ()) { + for (auto c = gsi::ClassBase::begin_classes (); c != gsi::ClassBase::end_classes (); ++c) { add_class_to_map (c.operator-> ()); } - for (gsi::ClassBase::class_iterator c = gsi::ClassBase::begin_new_classes (); c != gsi::ClassBase::end_new_classes (); ++c) { + for (auto c = gsi::ClassBase::begin_new_classes (); c != gsi::ClassBase::end_new_classes (); ++c) { add_class_to_map (c.operator-> ()); } } - if (! sp_ti_to_class) { + if (! sp_ti_to_class_index) { return 0; } else { - ti_to_class_map_t::const_iterator c = sp_ti_to_class->find (&ti); - if (c != sp_ti_to_class->end ()) { - return c->second; + auto c = sp_ti_to_class_index->find (&ti); + if (c != sp_ti_to_class_index->end ()) { + return sp_classes->operator[] (c->second); } else { // try name lookup - tname_to_class_map_t::const_iterator cn = sp_tname_to_class->find (std::string (ti.name ())); + auto cn = sp_tname_to_class->find (std::string (ti.name ())); if (cn != sp_tname_to_class->end ()) { // we can use this typeinfo as alias - sp_ti_to_class->insert (std::make_pair (&ti, cn->second)); + sp_ti_to_class_index->insert (std::make_pair (&ti, sp_class_to_index->operator[] (cn->second))); return cn->second; } else { return 0; diff --git a/src/tl/tl/tlVariant.cc b/src/tl/tl/tlVariant.cc index 7e46e0add..081dc9c53 100644 --- a/src/tl/tl/tlVariant.cc +++ b/src/tl/tl/tlVariant.cc @@ -144,22 +144,25 @@ struct VariantUserClassTableKey if (is_const != k.is_const) { return is_const < k.is_const; } - if (*type != *k.type) { - return type->before (*k.type); + if (type != k.type) { + return type < k.type; } return false; } bool operator== (const VariantUserClassTableKey &k) const { - return is_const == k.is_const && *type == *k.type; + return is_const == k.is_const && type == k.type; } const std::type_info *type; bool is_const; }; -static std::map *sp_class_table = 0; +static std::vector *sp_classes = 0; +static std::map *sp_class_to_index = 0; +static std::map, size_t> *sp_class_index_by_name = 0; +static std::map *sp_class_table = 0; static std::map s_user_type_by_name; void @@ -191,7 +194,7 @@ VariantUserClassBase::find_cls_by_name (const std::string &name) { tl_assert (! s_user_type_by_name.empty ()); - std::map ::const_iterator s = s_user_type_by_name.find (tl::to_lower_case (name)); + auto s = s_user_type_by_name.find (tl::to_lower_case (name)); if (s == s_user_type_by_name.end ()) { return 0; } @@ -199,33 +202,94 @@ VariantUserClassBase::find_cls_by_name (const std::string &name) return s->second; } +// type-info based interface + const tl::VariantUserClassBase *VariantUserClassBase::instance (const std::type_info &type, bool is_const) { tl_assert (sp_class_table != 0); - std::map::const_iterator c = sp_class_table->find (VariantUserClassTableKey (type, is_const)); - tl_assert (c != sp_class_table->end ()); - return c->second; + + const tl::VariantUserClassBase *inst = 0; + + auto c = sp_class_table->find (VariantUserClassTableKey (type, is_const)); + if (c == sp_class_table->end ()) { + + // fallback: lookup by name and update if required - sometimes, there may be two different type info objects for the same thing + auto c2i = sp_class_index_by_name->find (std::make_pair (std::string (type.name ()), is_const)); + tl_assert (c2i != sp_class_index_by_name->end ()); + sp_class_table->insert (std::make_pair (VariantUserClassTableKey (type, is_const), c2i->second)); + inst = sp_classes->operator[] (c2i->second); + + } else { + inst = sp_classes->operator[] (c->second); + } + + tl_assert (inst != 0); + return inst; } void VariantUserClassBase::register_instance (const tl::VariantUserClassBase *inst, const std::type_info &type, bool is_const) { if (! sp_class_table) { - sp_class_table = new std::map (); + sp_class_table = new std::map (); } - (*sp_class_table)[VariantUserClassTableKey (type, is_const)] = inst; + if (! sp_classes) { + sp_classes = new std::vector (); + } + if (! sp_class_index_by_name) { + sp_class_index_by_name = new std::map, size_t> (); + } + if (! sp_class_to_index) { + sp_class_to_index = new std::map (); + } + + size_t index = sp_class_to_index->insert (std::make_pair (inst, sp_classes->size ())).first->second; + if (index == sp_classes->size ()) { + sp_classes->push_back (inst); + } + + (*sp_class_table)[VariantUserClassTableKey (type, is_const)] = index; + (*sp_class_index_by_name) [std::make_pair (std::string (type.name ()), is_const)] = index; } void VariantUserClassBase::unregister_instance (const tl::VariantUserClassBase *inst, const std::type_info &type, bool is_const) { if (sp_class_table) { - std::map::iterator c = sp_class_table->find (VariantUserClassTableKey (type, is_const)); - if (c != sp_class_table->end () && c->second == inst) { + + auto c = sp_class_table->find (VariantUserClassTableKey (type, is_const)); + if (c != sp_class_table->end ()) { sp_class_table->erase (c); + sp_classes->operator[] (c->second) = 0; + while (!sp_classes->empty () && sp_classes->back () == 0) { + sp_classes->pop_back (); + } } + + auto cn = sp_class_index_by_name->find (std::make_pair (std::string (type.name ()), is_const)); + if (cn != sp_class_index_by_name->end ()) { + sp_class_index_by_name->erase (cn); + } + + sp_class_to_index->erase (inst); + if (sp_class_table->empty ()) { delete sp_class_table; sp_class_table = 0; } + + if (sp_classes->empty ()) { + delete sp_classes; + sp_classes = 0; + } + + if (sp_class_index_by_name->empty ()) { + delete sp_class_index_by_name; + sp_class_index_by_name = 0; + } + + if (sp_class_to_index->empty ()) { + delete sp_class_to_index; + sp_class_to_index = 0; + } } }