From c14d8cc877d4578730e80a66b639de1ab32bd7d0 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sat, 21 Feb 2026 20:44:02 +0100 Subject: [PATCH] [consider merging] proper cleanup of properties repo - this enables using user classes for names or values. Without this pre-finalization cleanup, the user class 'destroy' method may end up calling a method of an already destroyed class object. --- src/db/db/dbPropertiesRepository.cc | 13 +++++++++++-- src/db/unit_tests/dbPropertiesRepositoryTests.cc | 16 ++++++++++++++++ 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/src/db/db/dbPropertiesRepository.cc b/src/db/db/dbPropertiesRepository.cc index f10dd7050..22129dd52 100644 --- a/src/db/db/dbPropertiesRepository.cc +++ b/src/db/db/dbPropertiesRepository.cc @@ -27,6 +27,7 @@ #include "tlString.h" #include "tlAssert.h" #include "tlHash.h" +#include "tlStaticObjects.h" namespace db { @@ -348,13 +349,21 @@ PropertiesSet::hash () const // ---------------------------------------------------------------------------------- // PropertiesRepository implementation -static PropertiesRepository s_instance; +static PropertiesRepository *sp_global_instance = 0; static PropertiesRepository *sp_temp_instance = 0; PropertiesRepository & PropertiesRepository::instance () { - return sp_temp_instance ? *sp_temp_instance : s_instance; + if (sp_temp_instance) { + return *sp_temp_instance; + } else { + if (! sp_global_instance) { + sp_global_instance = new PropertiesRepository (); + tl::StaticObjects::reg (&sp_global_instance); + } + return *sp_global_instance; + } } void diff --git a/src/db/unit_tests/dbPropertiesRepositoryTests.cc b/src/db/unit_tests/dbPropertiesRepositoryTests.cc index 7363be12d..fe8dc27a3 100644 --- a/src/db/unit_tests/dbPropertiesRepositoryTests.cc +++ b/src/db/unit_tests/dbPropertiesRepositoryTests.cc @@ -503,3 +503,19 @@ TEST(SameValueDifferentTypes) EXPECT_EQ (db::property_name (rp.prop_name_id ((int) 5)).to_parsable_string (), "#5"); } } + +TEST(ComplexTypes) +{ + // This is also a smoke test: we intentionally register globally as the finalization code + // is critical: without the right destruction order we destroy the class object before the + // variant and trigger an assertion (pure virtual function called) + + db::PropertiesSet ps; + ps.insert (tl::Variant (17), db::DBox (0, 0, 1.5, 2.5)); + + db::properties_id_type pid = db::properties_id (ps); + + auto const &ps_out = db::properties (pid); + + EXPECT_EQ (ps_out.to_dict_var ().to_string (), "{17=>(0,0;1.5,2.5)}"); +}