]> OCCT Git - occt.git/commitdiff
Foundation Classes - Standard_Type avoiding C++ RTTI #236
authordpasukhi <dpasukhi@opencascade.com>
Sat, 4 Jan 2025 16:15:53 +0000 (16:15 +0000)
committerdpasukhi <dpasukhi@opencascade.com>
Sat, 4 Jan 2025 20:13:36 +0000 (20:13 +0000)
Refactor OCCT RTTI to not keep reference to std::type_info.
Deep copy is returned as before version 7.8.0.
Keep only owning information about classes.

src/Standard/Standard_Type.cxx
src/Standard/Standard_Type.hxx

index 875e7c3e5bee52871a308334d09ee38c43944b15..3da6f2c69fcada0302f326fac54ccfc31400e138 100644 (file)
@@ -1,5 +1,5 @@
 // Copyright (c) 1998-1999 Matra Datavision
-// Copyright (c) 1999-2014 OPEN CASCADE SAS
+// Copyright (c) 1999-2025 OPEN CASCADE SAS
 //
 // This file is part of Open CASCADE Technology software library.
 //
 // Alternatively, this file may be used under the terms of Open CASCADE
 // commercial license or contractual agreement.
 
-
 #include <Standard_Type.hxx>
-#include <Standard_Mutex.hxx>
-#include <Standard_Assert.hxx>
 
-#include <unordered_map>
+#include <NCollection_DataMap.hxx>
+#include <Standard_HashUtils.hxx>
+#include <Standard_Assert.hxx>
+#include <Standard_Mutex.hxx>
 
 IMPLEMENT_STANDARD_RTTIEXT(Standard_Type,Standard_Transient)
 
-//============================================================================
-
-Standard_Type::Standard_Type (const std::type_info& theInfo,
+Standard_Type::Standard_Type (const char* theSystemName,
                               const char* theName,
                               Standard_Size theSize,
                               const Handle(Standard_Type)& theParent) :
-  myInfo(theInfo),
+  mySystemName(theSystemName),
   myName(theName),
-  mySize(theSize), 
+  mySize(theSize),
   myParent(theParent)
 {}
 
@@ -79,14 +77,28 @@ void Standard_Type::Print (Standard_OStream& AStream) const
 //============================================================================
 
 namespace {
-  // Map of string to type
-  typedef std::unordered_map<std::type_index, Standard_Type*> registry_type;
+
+  struct typeNameHasher
+  {
+    size_t operator()(const Standard_CString theType) const noexcept
+    {
+      const int aLen = static_cast<int>(strlen(theType));
+      return opencascade::hashBytes(theType, aLen);
+    }
+
+    bool operator()(const Standard_CString theType1, const Standard_CString theType2) const noexcept
+    {
+      return strcmp(theType1, theType2) == 0;
+    }
+  };
+
+  using registry_type = NCollection_DataMap<Standard_CString, Standard_Type*, typeNameHasher>;
 
   // Registry is made static in the function to ensure that it gets
   // initialized by the time of first access
   registry_type& GetRegistry() 
   {
-    static registry_type theRegistry;
+    static registry_type theRegistry(2048, NCollection_BaseAllocator::CommonBaseAllocator());
     return theRegistry;
   }
 
@@ -99,21 +111,36 @@ Standard_Type* Standard_Type::Register (const std::type_info& theInfo, const cha
 {
   // Access to registry is protected by mutex; it should not happen often because
   // instances are cached by Standard_Type::Instance() (one per binary module)
-  static Standard_Mutex theMutex;
-  Standard_Mutex::Sentry aSentry (theMutex);
+  static Standard_Mutex aMutex;
+  Standard_Mutex::Sentry aSentry (aMutex);
 
   // return existing descriptor if already in the registry
   registry_type& aRegistry = GetRegistry();
-  Standard_Type* aType = 0;
-  auto anIter = aRegistry.find(theInfo);
-  if (anIter != aRegistry.end())
-    return anIter->second;
+  Standard_Type* aType;
+  if (aRegistry.Find(theInfo.name(), aType))
+  {
+    return aType;
+  }
+
+  // Calculate sizes for deep copies
+  const Standard_Size anInfoNameLen = strlen(theInfo.name()) + 1;
+  const Standard_Size aNameLen = strlen(theName) + 1;
+
+  // Allocate memory block for Standard_Type and the two strings
+  char* aMemoryBlock = static_cast<char*>(Standard::AllocateOptimal(sizeof(Standard_Type) + anInfoNameLen + aNameLen));
+
+  // Pointers to the locations for the deep copies of the strings
+  char* anInfoNameCopy = aMemoryBlock + sizeof(Standard_Type);
+  char* aNameCopy = anInfoNameCopy + anInfoNameLen;
+
+  // Deep copy the strings using strncpy
+  strncpy(anInfoNameCopy, theInfo.name(), anInfoNameLen);
+  strncpy(aNameCopy, theName, aNameLen);
 
-  // else create a new descriptor
-  aType = new Standard_Type (theInfo, theName, theSize, theParent);
+  aType = new (aMemoryBlock) Standard_Type(anInfoNameCopy, aNameCopy, theSize, theParent);
 
-  // then add it to registry and return (the reference to the handle stored in the registry)
-  aRegistry.emplace(theInfo, aType);
+  // Insert the descriptor into the registry
+  aRegistry.Bind(anInfoNameCopy, aType);
   return aType;
 }
 
@@ -121,5 +148,5 @@ Standard_Type::~Standard_Type ()
 {
   // remove descriptor from the registry
   registry_type& aRegistry = GetRegistry();
-  Standard_ASSERT(aRegistry.erase(myInfo) > 0, "Standard_Type::~Standard_Type() cannot find itself in registry",);
+  Standard_ASSERT(!aRegistry.UnBind(mySystemName), "Standard_Type::~Standard_Type() cannot find itself in registry",);
 }
index f13980270b3e6744933ac14e030434c57092a0ae..d3483d8bfc96af6c04e0cc3090859632a536cfb7 100644 (file)
@@ -102,7 +102,7 @@ class Standard_Type : public Standard_Transient
 public:
 
   //! Returns the system type name of the class (typeinfo.name)
-  Standard_CString SystemName() const { return myInfo.name(); }
+  Standard_CString SystemName() const { return mySystemName; }
   
   //! Returns the given name of the class type (get_type_name)
   Standard_CString Name() const { return myName; }
@@ -156,11 +156,11 @@ public:
 private:
 
   //! Constructor is private
-  Standard_Type (const std::type_info& theInfo, const char* theName,
+  Standard_Type (const char* theSystemName, const char* theName,
                  Standard_Size theSize, const Handle(Standard_Type)& theParent);
 
 private:
-  std::type_index myInfo;         //!< Object to store system name of the class
+  Standard_CString mySystemName;  //!< System name of the class
   Standard_CString myName;        //!< Given name of the class
   Standard_Size mySize;           //!< Size of the class instance, in bytes
   Handle(Standard_Type) myParent; //!< Type descriptor of parent class