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