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
ConfigVariableBool
This is a convenience class to specialize ConfigVariable as a boolean type.
Definition: configVariableBool.h:23
TypeHandle::is_derived_from
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
TypedReferenceCount
A base class for things which need to inherit from both TypedObject and from ReferenceCount.
Definition: typedReferenceCount.h:31
TypeHandle
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:81
memoryInfo.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
ConfigVariableBool::get_value
get_value
Returns the variable's value.
Definition: configVariableBool.h:40
typedReferenceCount.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
typeHandle.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.