Panda3D
memoryInfo.cxx
1 // Filename: memoryInfo.cxx
2 // Created by: drose (04Jun01)
3 //
4 ////////////////////////////////////////////////////////////////////
5 //
6 // PANDA 3D SOFTWARE
7 // Copyright (c) Carnegie Mellon University. All rights reserved.
8 //
9 // All use of this software is subject to the terms of the revised BSD
10 // license. You should have received a copy of this license along
11 // with this source code in a file named "LICENSE."
12 //
13 ////////////////////////////////////////////////////////////////////
14 
15 #include "memoryInfo.h"
16 
17 #ifdef DO_MEMORY_USAGE
18 
19 #include "typedReferenceCount.h"
20 #include "typeHandle.h"
21 
22 ////////////////////////////////////////////////////////////////////
23 // Function: MemoryInfo::Constructor
24 // Access: Public
25 // Description:
26 ////////////////////////////////////////////////////////////////////
27 MemoryInfo::
28 MemoryInfo() {
29  _void_ptr = (void *)NULL;
30  _ref_ptr = (ReferenceCount *)NULL;
31  _typed_ptr = (TypedObject *)NULL;
32  _size = 0;
33  _static_type = TypeHandle::none();
34  _dynamic_type = TypeHandle::none();
35 
36  _flags = 0;
37 }
38 
39 ////////////////////////////////////////////////////////////////////
40 // Function: MemoryInfo::get_type
41 // Access: Public
42 // Description: Returns the best known type, dynamic or static, of
43 // the pointer.
44 ////////////////////////////////////////////////////////////////////
45 TypeHandle MemoryInfo::
46 get_type() {
47  // If we don't want to consider the dynamic type any further, use
48  // what we've got.
49  if ((_flags & F_reconsider_dynamic_type) == 0) {
50  if (_dynamic_type == TypeHandle::none()) {
51  return _static_type;
52  }
53  return _dynamic_type;
54  }
55 
56  // Otherwise, examine the pointer again and make sure it's still the
57  // best information we have. We have to do this each time because
58  // if we happen to be examining the pointer from within the
59  // constructor or destructor, its dynamic type will appear to be
60  // less-specific than it actually is, so our idea of what type this
61  // thing is could change from time to time.
62  determine_dynamic_type();
63 
64  // Now return the more specific of the two.
65  TypeHandle type = _static_type;
66  update_type_handle(type, _dynamic_type);
67 
68  if (type != _static_type) {
69  if (express_cat.is_spam()) {
70  express_cat.spam()
71  << "Pointer " << get_void_ptr() << " has static type "
72  << _static_type << " and dynamic type " << _dynamic_type << "\n";
73  }
74  }
75 
76  return type;
77 }
78 
79 ////////////////////////////////////////////////////////////////////
80 // Function: MemoryInfo::determine_dynamic_type
81 // Access: Private
82 // Description: Tries to determine the actual type of the object to
83 // which this thing is pointed, if possible.
84 ////////////////////////////////////////////////////////////////////
85 void MemoryInfo::
86 determine_dynamic_type() {
87  if ((_flags & F_reconsider_dynamic_type) != 0 &&
88  _static_type != TypeHandle::none()) {
89  // See if we know enough now to infer the dynamic type from the
90  // pointer.
91 
92  if (_typed_ptr == (TypedObject *)NULL) {
93  // If our static type is known to inherit from
94  // TypedReferenceCount, then we can directly downcast to get the
95  // TypedObject pointer.
96  if (_static_type.is_derived_from(TypedReferenceCount::get_class_type())) {
97  _typed_ptr = (TypedReferenceCount *)_ref_ptr;
98  }
99  }
100 
101  if (_typed_ptr != (TypedObject *)NULL) {
102  // If we have a TypedObject pointer, we can determine the type.
103  // This might still not return the exact type, particularly if
104  // we are being called within the destructor or constructor of
105  // this object.
106  TypeHandle got_type = _typed_ptr->get_type();
107 
108  if (got_type == TypeHandle::none()) {
109  express_cat.warning()
110  << "Found an unregistered type in a " << _static_type
111  << " pointer:\n"
112  << "Check derived types of " << _static_type
113  << " and make sure that all are being initialized.\n";
114  _dynamic_type = _static_type;
115  _flags &= ~F_reconsider_dynamic_type;
116 
117  if (ConfigVariableBool("raise-unregistered-type", false).get_value()) {
118  nassert_raise("Unregistered type");
119  }
120  return;
121  }
122 
123  TypeHandle orig_type = _dynamic_type;
124  update_type_handle(_dynamic_type, got_type);
125  }
126  }
127 }
128 
129 
130 ////////////////////////////////////////////////////////////////////
131 // Function: MemoryInfo::update_type_handle
132 // Access: Private
133 // Description: Updates the given destination TypeHandle with the
134 // refined TypeHandle, if it is in fact more specific
135 // than the original value for the destination. Returns
136 // true if the update was trouble-free, or false if the
137 // two types were not apparently related.
138 ////////////////////////////////////////////////////////////////////
139 bool MemoryInfo::
140 update_type_handle(TypeHandle &destination, TypeHandle refined) {
141  if (refined == TypeHandle::none()) {
142  express_cat.error()
143  << "Attempt to update type of " << get_void_ptr()
144  << "(type is " << get_type()
145  << ") to an undefined type!\n";
146 
147  } else if (destination == refined) {
148  // Updating with the same type, no problem.
149 
150  } else if (destination.is_derived_from(refined)) {
151  // Updating with a less-specific type, no problem.
152 
153  } else if (destination == TypeHandle::none() ||
154  refined.is_derived_from(destination)) {
155  // Updating with a more-specific type, no problem.
156  if (express_cat.is_spam()) {
157  express_cat.spam()
158  << "Updating " << get_void_ptr() << " from type "
159  << destination << " to type " << refined << "\n";
160  }
161  destination = refined;
162 
163  } else {
164  // Unrelated types, which might or might not be a problem.
165  express_cat.warning()
166  << "Pointer " << get_void_ptr() << " previously indicated as type "
167  << destination << " is now type " << refined << "!\n";
168  return false;
169  }
170 
171  return true;
172 }
173 
174 #endif // DO_MEMORY_USAGE
static TypeHandle none()
Returns a special zero-valued TypeHandle that is used to indicate no type.
Definition: typeHandle.I:274
bool is_derived_from(TypeHandle parent, TypedObject *object=(TypedObject *) NULL) const
Returns true if this type is derived from the indicated type, false otherwise.
Definition: typeHandle.I:152
This is a convenience class to specialize ConfigVariable as a boolean type.
A base class for things which need to inherit from both TypedObject and from ReferenceCount.
This is an abstract class that all classes which use TypeHandle, and also provide virtual functions t...
Definition: typedObject.h:98
A base class for all things that want to be reference-counted.
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:85