0030901: Visualization - OSD_MemInfo moving memory computation out of the constructor
[occt.git] / src / Standard / Standard_Type.cxx
1 // Copyright (c) 1998-1999 Matra Datavision
2 // Copyright (c) 1999-2014 OPEN CASCADE SAS
3 //
4 // This file is part of Open CASCADE Technology software library.
5 //
6 // This library is free software; you can redistribute it and/or modify it under
7 // the terms of the GNU Lesser General Public License version 2.1 as published
8 // by the Free Software Foundation, with special exception defined in the file
9 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
10 // distribution for complete text of the license and disclaimer of any warranty.
11 //
12 // Alternatively, this file may be used under the terms of Open CASCADE
13 // commercial license or contractual agreement.
14
15
16 #include <Standard_Type.hxx>
17 #include <Standard_Mutex.hxx>
18 #include <Standard_Assert.hxx>
19
20 #include <NCollection_DataMap.hxx>
21
22 IMPLEMENT_STANDARD_RTTIEXT(Standard_Type,Standard_Transient)
23
24 //============================================================================
25
26 namespace {
27 static Standard_CString copy_string (const char* theString)
28 {
29   size_t aLength = strlen (theString);
30   char* aResult = static_cast<char*> (Standard::Allocate (aLength + 1));
31   strncpy (aResult, theString, aLength + 1); //including null-character
32   return aResult;
33 }
34 }
35
36 Standard_Type::Standard_Type (const char* theSystemName,
37                               const char* theName,
38                               Standard_Size theSize,
39                               const Handle(Standard_Type)& theParent) :
40   mySystemName(copy_string (theSystemName)),
41   myName(copy_string (theName)), 
42   mySize(theSize), 
43   myParent(theParent)
44 {
45 }
46
47 //============================================================================
48
49 Standard_Boolean Standard_Type::SubType (const Handle(Standard_Type)& theOther) const
50 {
51   return ! theOther.IsNull() && (theOther == this || (! myParent.IsNull() && myParent->SubType (theOther)));
52 }
53
54 //============================================================================
55
56 Standard_Boolean Standard_Type::SubType (const Standard_CString theName) const
57 {
58   return theName != 0 && (IsEqual (myName, theName) || (! myParent.IsNull() && myParent->SubType (theName)));
59 }
60
61 // ------------------------------------------------------------------
62 // Print (me; s: in out OStream) returns OStream;
63 // ------------------------------------------------------------------
64 void Standard_Type::Print (Standard_OStream& AStream) const
65 {
66   AStream << std::hex << (Standard_Address)this << " : " << std::dec << myName ;
67 }
68
69 //============================================================================
70 // Registry of types
71 //============================================================================
72
73 namespace {
74   // Value-based hasher for plain C string (char*)
75   struct CStringHasher 
76   {
77     //! Computes a hash code of the given Standard_CString, in the range [1, theUpperBound]
78     //! @param theKey the key which hash code is to be computed
79     //! @param theUpperBound the upper bound of the range a computing hash code must be within
80     //! @return a computed hash code, in the range [1, theUpperBound]
81     static Standard_Integer HashCode (const Standard_CString& theKey, const Standard_Integer theUpperBound)
82     {
83       return ::HashCode (theKey, theUpperBound);
84     }
85     static bool IsEqual (const Standard_CString& theKey1, const Standard_CString& theKey2)
86     {
87       return ! strcmp (theKey1, theKey2);
88     }
89   };
90
91   // Map of string to type
92   typedef NCollection_DataMap<Standard_CString, Standard_Type*, CStringHasher> registry_type;
93
94   // Registry is made static in the function to ensure that it gets
95   // initialized by the time of first access
96   registry_type& GetRegistry() 
97   {
98     static registry_type theRegistry;
99     return theRegistry;
100   }
101 }
102
103 Standard_Type* Standard_Type::Register (const char* theSystemName, const char* theName,
104                                         Standard_Size theSize, const Handle(Standard_Type)& theParent)
105 {
106   // Access to registry is protected by mutex; it should not happen often because
107   // instances are cached by Standard_Type::Instance() (one per binary module)
108   static Standard_Mutex theMutex;
109   Standard_Mutex::Sentry aSentry (theMutex);
110
111   // return existing descriptor if already in the registry
112   registry_type& aRegistry = GetRegistry();
113   Standard_Type* aType = 0;
114   if (aRegistry.Find (theSystemName, aType))
115     return aType;
116
117   // else create a new descriptor
118   aType = new Standard_Type (theSystemName, theName, theSize, theParent);
119
120   // then add it to registry and return (the reference to the handle stored in the registry)
121   aRegistry.Bind (aType->mySystemName, aType);
122
123 //  std::cout << "Registering " << theSystemName << ": " << aRegistry.Extent() << std::endl;
124
125   return aType;
126 }
127
128 Standard_Type::~Standard_Type ()
129 {
130   // remove descriptor from the registry
131   registry_type& aRegistry = GetRegistry();
132   Standard_ASSERT(aRegistry.UnBind (mySystemName), "Standard_Type::~Standard_Type() cannot find itself in registry",);
133
134 //  std::cout << "Unregistering " << mySystemName << ": " << aRegistry.Extent() << std::endl;
135   Standard::Free (mySystemName);
136   Standard::Free (myName);
137 }