From a39bc587c128d760bca2dad6d94c5268acaa1633 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Fri, 3 Apr 2026 17:49:29 +0200 Subject: [PATCH] Reusing libraries inside Library#library_from_file and Library#library:from_files for conservative reloading. --- src/db/db/dbFileBasedLibrary.cc | 21 +++++++++++++++++++ src/db/db/dbFileBasedLibrary.h | 10 +++++++++ src/db/db/gsiDeclDbLibrary.cc | 36 +++++++++++++++++++++++++++++---- 3 files changed, 63 insertions(+), 4 deletions(-) diff --git a/src/db/db/dbFileBasedLibrary.cc b/src/db/db/dbFileBasedLibrary.cc index 10025e650..e13fd927f 100644 --- a/src/db/db/dbFileBasedLibrary.cc +++ b/src/db/db/dbFileBasedLibrary.cc @@ -53,6 +53,27 @@ FileBasedLibrary::merge_with_other_layout (const std::string &path) } } +bool +FileBasedLibrary::is_for_path (const std::string &path) +{ + return m_other_paths.empty () && m_path == path; +} + +bool +FileBasedLibrary::is_for_paths (const std::vector &paths) +{ + if (paths.size () != m_other_paths.size () + 1) { + return false; + } + + // this check is purely based on path strings + std::set p1 (paths.begin (), paths.end ()); + std::set p2; + p2.insert (m_path); + p2.insert (m_other_paths.begin (), m_other_paths.end ()); + return p1 == p2; +} + std::string FileBasedLibrary::load () { diff --git a/src/db/db/dbFileBasedLibrary.h b/src/db/db/dbFileBasedLibrary.h index 921ebe383..3a9ddaee9 100644 --- a/src/db/db/dbFileBasedLibrary.h +++ b/src/db/db/dbFileBasedLibrary.h @@ -89,6 +89,16 @@ public: m_other_paths = other_paths; } + /** + * @brief Gets a value indicating whether the library is for the given path + */ + bool is_for_path (const std::string &path); + + /** + * @brief Gets a value indicating whether the library is for the given path + */ + bool is_for_paths (const std::vector &paths); + private: std::string m_name; std::string m_path; diff --git a/src/db/db/gsiDeclDbLibrary.cc b/src/db/db/gsiDeclDbLibrary.cc index a3e412211..69e9280c0 100644 --- a/src/db/db/gsiDeclDbLibrary.cc +++ b/src/db/db/gsiDeclDbLibrary.cc @@ -157,9 +157,21 @@ static LibraryImpl *new_lib () return new LibraryImpl (); } -static db::Library *library_from_file (const std::string &path, const std::string &name) +static db::Library *library_from_file (const std::string &path, const std::string &name, const std::string &for_technology) { + // Check if a library with this specification already is installed and reuse in that case. + if (! name.empty ()) { + + db::FileBasedLibrary *old_lib = dynamic_cast (library_by_name (name, for_technology)); + if (old_lib && old_lib->is_for_path (path)) { + old_lib->load (); + return old_lib; + } + + } + std::unique_ptr lib (new db::FileBasedLibrary (path, name)); + lib->set_technology (for_technology); std::string n = lib->load (); db::Library *ret = lib.get (); @@ -168,17 +180,30 @@ static db::Library *library_from_file (const std::string &path, const std::strin return ret; } -static db::Library *library_from_files (const std::vector &paths, const std::string &name) +static db::Library *library_from_files (const std::vector &paths, const std::string &name, const std::string &for_technology) { if (paths.empty ()) { throw tl::Exception (tl::to_string (tr ("At least one path must be given"))); } + // Check if a library with this specification already is installed and reuse in that case. + if (! name.empty ()) { + + db::FileBasedLibrary *old_lib = dynamic_cast (library_by_name (name, for_technology)); + if (old_lib && old_lib->is_for_paths (paths)) { + old_lib->load (); + return old_lib; + } + + } + std::unique_ptr lib (new db::FileBasedLibrary (paths.front (), name)); for (auto i = paths.begin () + 1; i != paths.end (); ++i) { lib->merge_with_other_layout (*i); } + lib->set_technology (for_technology); + std::string n = lib->load (); db::Library *ret = lib.get (); register_lib (lib.release (), n); @@ -191,7 +216,7 @@ static db::Library *library_from_files (const std::vector &paths, */ LibraryClass decl_Library ("db", "LibraryBase", - gsi::method ("library_from_file", &library_from_file, gsi::arg ("path"), gsi::arg ("name", std::string (), "auto"), + gsi::method ("library_from_file", &library_from_file, gsi::arg ("path"), gsi::arg ("name", std::string (), "auto"), gsi::arg ("for_technology", std::string (), "none"), "@brief Creates a library from a file\n" "@param path The path to the file from which to create the library from.\n" "@param name The name of the library. If empty, the name will be derived from the GDS LIBNAME or the file name.\n" @@ -200,9 +225,12 @@ LibraryClass decl_Library ("db", "LibraryBase", "This method will create a \\Library object which is tied to a specific file. This object supports " "automatic reloading when the \\Library#refresh method is called.\n" "\n" + "If a file-based library with the same name and path is registered already, this method will not reload again " + "and return the library that was already registered.\n" + "\n" "This convenience method has been added in version 0.30.8.\n" ) + - gsi::method ("library_from_files", &library_from_files, gsi::arg ("paths"), gsi::arg ("name", std::string (), "auto"), + gsi::method ("library_from_files", &library_from_files, gsi::arg ("paths"), gsi::arg ("name", std::string (), "auto"), gsi::arg ("for_technology", std::string (), "none"), "@brief Creates a library from a set of files\n" "@param paths The paths to the files from which to create the library from. At least one file needs to be given.\n" "@param name The name of the library. If empty, the name will be derived from the GDS LIBNAME or the file name.\n"