From b1661d3c5ef9058c8b45bab23d5d8f8c81946631 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20K=C3=B6fferlein?= Date: Sun, 17 Jul 2022 19:59:29 +0200 Subject: [PATCH 1/3] Issue 1106 (#1107) * Help browser problem mitigation: on Qt6 (?), QTextBrowser appears to be reloading images relative to the new URL on a URL change. This caused 'missing resource' exceptions. As long as the root cause of this problem is not know, the exceptions are turned into log errors now. * Fixed issue 1106 --- src/edt/edt/edtPartialService.cc | 5 +---- src/layui/layui/layBrowserPanel.cc | 27 +++++++++++++++++++-------- 2 files changed, 20 insertions(+), 12 deletions(-) diff --git a/src/edt/edt/edtPartialService.cc b/src/edt/edt/edtPartialService.cc index aeec8335c..e50f94f82 100644 --- a/src/edt/edt/edtPartialService.cc +++ b/src/edt/edt/edtPartialService.cc @@ -1466,9 +1466,6 @@ PartialService::transform_selection (const db::DTrans &move_trans) // then move all instances. - // TODO: DTrans should have a ctor that takes a vector - db::DTrans move_trans_inst = db::DTrans (db::DVector () + lay::snap_angle (m_current - m_start, move_ac ())); - // sort the selected objects (the instances) by the cell they are in // The key is a pair: cell_index, cv_index std::map , std::vector > insts_by_cell; @@ -1494,7 +1491,7 @@ PartialService::transform_selection (const db::DTrans &move_trans) if (tv_list && ! tv_list->empty ()) { db::CplxTrans tt = (*tv_list) [0] * db::CplxTrans (cv->layout ().dbu ()) * cv.context_trans (); - db::ICplxTrans move_trans_dbu (tt.inverted () * db::DCplxTrans (move_trans_inst) * tt); + db::ICplxTrans move_trans_dbu (tt.inverted () * db::DCplxTrans (move_trans) * tt); std::sort (insts_to_transform.begin (), insts_to_transform.end ()); std::vector >::const_iterator unique_end = std::unique (insts_to_transform.begin (), insts_to_transform.end ()); diff --git a/src/layui/layui/layBrowserPanel.cc b/src/layui/layui/layBrowserPanel.cc index 75d0a0a08..1f46f5858 100644 --- a/src/layui/layui/layBrowserPanel.cc +++ b/src/layui/layui/layBrowserPanel.cc @@ -674,16 +674,24 @@ BrowserPanel::loadResource (int type, const QUrl &url) { if (type == QTextDocument::ImageResource) { - BEGIN_PROTECTED - return QVariant (mp_source->get_image (tl::to_string (url.toString ()))); - END_PROTECTED + try { + return QVariant (mp_source->get_image (tl::to_string (url.toString ()))); + } catch (tl::Exception &ex) { + tl::error << ex.msg (); + } catch (...) { + } + return QVariant (); } else if (type == QTextDocument::StyleSheetResource) { - BEGIN_PROTECTED - return QVariant (tl::to_qstring (mp_source->get_css (tl::to_string (url.toString ())))); - END_PROTECTED + try { + return QVariant (tl::to_qstring (mp_source->get_css (tl::to_string (url.toString ())))); + } catch (tl::Exception &ex) { + tl::error << ex.msg (); + } catch (...) { + } + return QVariant (); } else if (type != QTextDocument::HtmlResource) { @@ -707,7 +715,7 @@ BrowserPanel::loadResource (int type, const QUrl &url) // (normal) override cursor. QApplication::setOverrideCursor (QCursor (Qt::ArrowCursor)); - BEGIN_PROTECTED + try { std::string u = tl::to_string (url.toString ()); std::string s; @@ -756,7 +764,10 @@ BrowserPanel::loadResource (int type, const QUrl &url) // push the outline set_outline (ol); - END_PROTECTED + } catch (tl::Exception &ex) { + tl::error << ex.msg (); + } catch (...) { + } QApplication::restoreOverrideCursor (); 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 2/3] 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; + } } } From 24e8db996cd598df9c2dcedcb0846f3964fb077f Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Mon, 18 Jul 2022 00:16:56 +0200 Subject: [PATCH 3/3] Avoid a segfault on exit --- src/tl/tl/tlVariant.cc | 45 +++++++++++++++++++++++------------------- 1 file changed, 25 insertions(+), 20 deletions(-) diff --git a/src/tl/tl/tlVariant.cc b/src/tl/tl/tlVariant.cc index 081dc9c53..33ce5d7e7 100644 --- a/src/tl/tl/tlVariant.cc +++ b/src/tl/tl/tlVariant.cc @@ -254,42 +254,47 @@ void VariantUserClassBase::register_instance (const tl::VariantUserClassBase *in void VariantUserClassBase::unregister_instance (const tl::VariantUserClassBase *inst, const std::type_info &type, bool is_const) { if (sp_class_table) { - 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 (); + if (sp_classes) { + sp_classes->operator[] (c->second) = 0; + while (!sp_classes->empty () && sp_classes->back () == 0) { + sp_classes->pop_back (); + } } } + } + if (sp_class_index_by_name) { 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); } + } + if (sp_class_to_index) { sp_class_to_index->erase (inst); + } - if (sp_class_table->empty ()) { - delete sp_class_table; - sp_class_table = 0; - } + if (sp_class_table && sp_class_table->empty ()) { + delete sp_class_table; + sp_class_table = 0; + } - if (sp_classes->empty ()) { - delete sp_classes; - sp_classes = 0; - } + if (sp_classes && 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_index_by_name && 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; - } + if (sp_class_to_index && sp_class_to_index->empty ()) { + delete sp_class_to_index; + sp_class_to_index = 0; } }