1 /*=========================================================================
2 
3   Program:   Visualization Toolkit
4   Module:    vtkObjectBase.cxx
5 
6   Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
7   All rights reserved.
8   See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
9 
10      This software is distributed WITHOUT ANY WARRANTY; without even
11      the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
12      PURPOSE.  See the above copyright notice for more information.
13 
14 =========================================================================*/
15 
16 #include "vtkObjectBase.h"
17 #include "vtkDebugLeaks.h"
18 #include "vtkGarbageCollector.h"
19 #include "vtkWeakPointerBase.h"
20 
21 #include <sstream>
22 
23 #define vtkBaseDebugMacro(x)
24 
25 class vtkObjectBaseToGarbageCollectorFriendship
26 {
27 public:
GiveReference(vtkObjectBase * obj)28   static int GiveReference(vtkObjectBase* obj)
29   {
30     return vtkGarbageCollector::GiveReference(obj);
31   }
TakeReference(vtkObjectBase * obj)32   static int TakeReference(vtkObjectBase* obj)
33   {
34     return vtkGarbageCollector::TakeReference(obj);
35   }
36 };
37 
38 class vtkObjectBaseToWeakPointerBaseFriendship
39 {
40 public:
ClearPointer(vtkWeakPointerBase * p)41   static void ClearPointer(vtkWeakPointerBase *p)
42   {
43     p->Object = nullptr;
44   }
45 };
46 
47 // avoid dll boundary problems
48 #ifdef _WIN32
operator new(size_t nSize)49 void* vtkObjectBase::operator new(size_t nSize)
50 {
51   void* p=malloc(nSize);
52   return p;
53 }
54 
operator delete(void * p)55 void vtkObjectBase::operator delete( void *p )
56 {
57   free(p);
58 }
59 #endif
60 
61 // ------------------------------------vtkObjectBase----------------------
62 // This operator allows all subclasses of vtkObjectBase to be printed via <<.
63 // It in turn invokes the Print method, which in turn will invoke the
64 // PrintSelf method that all objects should define, if they have anything
65 // interesting to print out.
operator <<(ostream & os,vtkObjectBase & o)66 ostream& operator<<(ostream& os, vtkObjectBase& o)
67 {
68   o.Print(os);
69   return os;
70 }
71 
72 // Create an object with Debug turned off and modified time initialized
73 // to zero.
vtkObjectBase()74 vtkObjectBase::vtkObjectBase()
75 {
76   this->ReferenceCount = 1;
77   this->WeakPointers = nullptr;
78 #ifdef VTK_DEBUG_LEAKS
79   vtkDebugLeaks::ConstructingObject(this);
80 #endif
81 }
82 
~vtkObjectBase()83 vtkObjectBase::~vtkObjectBase()
84 {
85 #ifdef VTK_DEBUG_LEAKS
86   vtkDebugLeaks::DestructingObject(this);
87 #endif
88 
89   // warn user if reference counting is on and the object is being referenced
90   // by another object
91   if ( this->ReferenceCount > 0)
92   {
93     vtkGenericWarningMacro(<< "Trying to delete object with non-zero reference count.");
94   }
95 }
96 
97 //----------------------------------------------------------------------------
InitializeObjectBase()98 void vtkObjectBase::InitializeObjectBase()
99 {
100 #ifdef VTK_DEBUG_LEAKS
101   vtkDebugLeaks::ConstructClass(this->GetClassName());
102 #endif // VTK_DEBUG_LEAKS
103 }
104 
105 //----------------------------------------------------------------------------
106 #ifdef VTK_WORKAROUND_WINDOWS_MANGLE
107 # undef GetClassName
108 // Define possible mangled names.
GetClassNameA() const109 const char* vtkObjectBase::GetClassNameA() const
110 {
111   return this->GetClassNameInternal();
112 }
GetClassNameW() const113 const char* vtkObjectBase::GetClassNameW() const
114 {
115   return this->GetClassNameInternal();
116 }
117 #endif
GetClassName() const118 const char* vtkObjectBase::GetClassName() const
119 {
120   return this->GetClassNameInternal();
121 }
122 
IsTypeOf(const char * name)123 vtkTypeBool vtkObjectBase::IsTypeOf(const char *name)
124 {
125   if ( !strcmp("vtkObjectBase",name) )
126   {
127     return 1;
128   }
129   return 0;
130 }
131 
IsA(const char * type)132 vtkTypeBool vtkObjectBase::IsA(const char *type)
133 {
134   return this->vtkObjectBase::IsTypeOf(type);
135 }
136 
137 // Delete a vtk object. This method should always be used to delete an object
138 // when the new operator was used to create it. Using the C++ delete method
139 // will not work with reference counting.
Delete()140 void vtkObjectBase::Delete()
141 {
142   this->UnRegister(static_cast<vtkObjectBase *>(nullptr));
143 }
144 
FastDelete()145 void vtkObjectBase::FastDelete()
146 {
147   // Remove the reference without doing a collection check even if
148   // this object normally participates in garbage collection.
149   this->UnRegisterInternal(nullptr, 0);
150 }
151 
Print(ostream & os)152 void vtkObjectBase::Print(ostream& os)
153 {
154   vtkIndent indent;
155 
156   this->PrintHeader(os,vtkIndent(0));
157   this->PrintSelf(os, indent.GetNextIndent());
158   this->PrintTrailer(os,vtkIndent(0));
159 }
160 
PrintHeader(ostream & os,vtkIndent indent)161 void vtkObjectBase::PrintHeader(ostream& os, vtkIndent indent)
162 {
163   os << indent << this->GetClassName() << " (" << this << ")\n";
164 }
165 
166 // Chaining method to print an object's instance variables, as well as
167 // its superclasses.
PrintSelf(ostream & os,vtkIndent indent)168 void vtkObjectBase::PrintSelf(ostream& os, vtkIndent indent)
169 {
170   os << indent << "Reference Count: " << this->ReferenceCount << "\n";
171 }
172 
PrintTrailer(ostream & os,vtkIndent indent)173 void vtkObjectBase::PrintTrailer(ostream& os, vtkIndent indent)
174 {
175   os << indent << "\n";
176 }
177 
178 // Description:
179 // Sets the reference count (use with care)
SetReferenceCount(int ref)180 void vtkObjectBase::SetReferenceCount(int ref)
181 {
182   this->ReferenceCount = ref;
183   vtkBaseDebugMacro(<< "Reference Count set to " << this->ReferenceCount);
184 }
185 
186 //----------------------------------------------------------------------------
Register(vtkObjectBase * o)187 void vtkObjectBase::Register(vtkObjectBase* o)
188 {
189   // Do not participate in garbage collection by default.
190   this->RegisterInternal(o, 0);
191 }
192 
193 //----------------------------------------------------------------------------
UnRegister(vtkObjectBase * o)194 void vtkObjectBase::UnRegister(vtkObjectBase* o)
195 {
196   // Do not participate in garbage collection by default.
197   this->UnRegisterInternal(o, 0);
198 }
199 
200 //----------------------------------------------------------------------------
RegisterInternal(vtkObjectBase *,vtkTypeBool check)201 void vtkObjectBase::RegisterInternal(vtkObjectBase*, vtkTypeBool check)
202 {
203   // If a reference is available from the garbage collector, use it.
204   // Otherwise create a new reference by incrementing the reference
205   // count.
206   if(!(check &&
207        vtkObjectBaseToGarbageCollectorFriendship::TakeReference(this)))
208   {
209     this->ReferenceCount++;
210   }
211 }
212 
213 //----------------------------------------------------------------------------
UnRegisterInternal(vtkObjectBase *,vtkTypeBool check)214 void vtkObjectBase::UnRegisterInternal(vtkObjectBase*, vtkTypeBool check)
215 {
216   // If the garbage collector accepts a reference, do not decrement
217   // the count.
218   if(check && this->ReferenceCount > 1 &&
219      vtkObjectBaseToGarbageCollectorFriendship::GiveReference(this))
220   {
221     return;
222   }
223 
224   // Decrement the reference count, delete object if count goes to zero.
225   if(--this->ReferenceCount <= 0)
226   {
227     // Clear all weak pointers to the object before deleting it.
228     if (this->WeakPointers)
229     {
230       vtkWeakPointerBase **p = this->WeakPointers;
231       while (*p)
232       {
233         vtkObjectBaseToWeakPointerBaseFriendship::ClearPointer(*p++);
234       }
235       delete [] this->WeakPointers;
236     }
237 #ifdef VTK_DEBUG_LEAKS
238     vtkDebugLeaks::DestructClass(this->GetClassName());
239 #endif
240     delete this;
241   }
242   else if(check)
243   {
244     // The garbage collector did not accept the reference, but the
245     // object still exists and is participating in garbage collection.
246     // This means either that delayed garbage collection is disabled
247     // or the collector has decided it is time to do a check.
248     vtkGarbageCollector::Collect(this);
249   }
250 }
251 
252 //----------------------------------------------------------------------------
ReportReferences(vtkGarbageCollector *)253 void vtkObjectBase::ReportReferences(vtkGarbageCollector*)
254 {
255   // vtkObjectBase has no references to report.
256 }
257