Panda3D

memoryInfo.cxx

00001 // Filename: memoryInfo.cxx
00002 // Created by:  drose (04Jun01)
00003 //
00004 ////////////////////////////////////////////////////////////////////
00005 //
00006 // PANDA 3D SOFTWARE
00007 // Copyright (c) Carnegie Mellon University.  All rights reserved.
00008 //
00009 // All use of this software is subject to the terms of the revised BSD
00010 // license.  You should have received a copy of this license along
00011 // with this source code in a file named "LICENSE."
00012 //
00013 ////////////////////////////////////////////////////////////////////
00014 
00015 #include "memoryInfo.h"
00016 
00017 #ifdef DO_MEMORY_USAGE
00018 
00019 #include "typedReferenceCount.h"
00020 #include "typeHandle.h"
00021 
00022 ////////////////////////////////////////////////////////////////////
00023 //     Function: MemoryInfo::Constructor
00024 //       Access: Public
00025 //  Description: 
00026 ////////////////////////////////////////////////////////////////////
00027 MemoryInfo::
00028 MemoryInfo() {
00029   _void_ptr = (void *)NULL;
00030   _ref_ptr = (ReferenceCount *)NULL;
00031   _typed_ptr = (TypedObject *)NULL;
00032   _size = 0;
00033   _static_type = TypeHandle::none();
00034   _dynamic_type = TypeHandle::none();
00035 
00036   _flags = 0;
00037 }
00038 
00039 ////////////////////////////////////////////////////////////////////
00040 //     Function: MemoryInfo::get_type
00041 //       Access: Public
00042 //  Description: Returns the best known type, dynamic or static, of
00043 //               the pointer.
00044 ////////////////////////////////////////////////////////////////////
00045 TypeHandle MemoryInfo::
00046 get_type() {
00047   // If we don't want to consider the dynamic type any further, use
00048   // what we've got.
00049   if ((_flags & F_reconsider_dynamic_type) == 0) {
00050     if (_dynamic_type == TypeHandle::none()) {
00051       return _static_type;
00052     }
00053     return _dynamic_type;
00054   }
00055 
00056   // Otherwise, examine the pointer again and make sure it's still the
00057   // best information we have.  We have to do this each time because
00058   // if we happen to be examining the pointer from within the
00059   // constructor or destructor, its dynamic type will appear to be
00060   // less-specific than it actually is, so our idea of what type this
00061   // thing is could change from time to time.
00062   determine_dynamic_type();
00063 
00064   // Now return the more specific of the two.
00065   TypeHandle type = _static_type;
00066   update_type_handle(type, _dynamic_type);
00067 
00068   if (type != _static_type) {
00069     if (express_cat.is_spam()) {
00070       express_cat.spam()
00071         << "Pointer " << get_void_ptr() << " has static type "
00072         << _static_type << " and dynamic type " << _dynamic_type << "\n";
00073     }
00074   }
00075 
00076   return type;
00077 }
00078 
00079 ////////////////////////////////////////////////////////////////////
00080 //     Function: MemoryInfo::determine_dynamic_type
00081 //       Access: Private
00082 //  Description: Tries to determine the actual type of the object to
00083 //               which this thing is pointed, if possible.
00084 ////////////////////////////////////////////////////////////////////
00085 void MemoryInfo::
00086 determine_dynamic_type() {
00087   if ((_flags & F_reconsider_dynamic_type) != 0 &&
00088       _static_type != TypeHandle::none()) {
00089     // See if we know enough now to infer the dynamic type from the
00090     // pointer.
00091 
00092     if (_typed_ptr == (TypedObject *)NULL) {
00093       // If our static type is known to inherit from
00094       // TypedReferenceCount, then we can directly downcast to get the
00095       // TypedObject pointer.
00096       if (_static_type.is_derived_from(TypedReferenceCount::get_class_type())) {
00097         _typed_ptr = (TypedReferenceCount *)_ref_ptr;
00098       }
00099     }
00100 
00101     if (_typed_ptr != (TypedObject *)NULL) {
00102       // If we have a TypedObject pointer, we can determine the type.
00103       // This might still not return the exact type, particularly if
00104       // we are being called within the destructor or constructor of
00105       // this object.
00106       TypeHandle got_type = _typed_ptr->get_type();
00107 
00108       if (got_type == TypeHandle::none()) {
00109         express_cat.warning()
00110           << "Found an unregistered type in a " << _static_type
00111           << " pointer:\n"
00112           << "Check derived types of " << _static_type
00113           << " and make sure that all are being initialized.\n";
00114         _dynamic_type = _static_type;
00115         _flags &= ~F_reconsider_dynamic_type;
00116 
00117         if (ConfigVariableBool("raise-unregistered-type", false).get_value()) {
00118           nassert_raise("Unregistered type");
00119         }
00120         return;
00121       }
00122 
00123       TypeHandle orig_type = _dynamic_type;
00124       update_type_handle(_dynamic_type, got_type);
00125     }    
00126   }
00127 }
00128 
00129 
00130 ////////////////////////////////////////////////////////////////////
00131 //     Function: MemoryInfo::update_type_handle
00132 //       Access: Private
00133 //  Description: Updates the given destination TypeHandle with the
00134 //               refined TypeHandle, if it is in fact more specific
00135 //               than the original value for the destination.  Returns
00136 //               true if the update was trouble-free, or false if the
00137 //               two types were not apparently related.
00138 ////////////////////////////////////////////////////////////////////
00139 bool MemoryInfo::
00140 update_type_handle(TypeHandle &destination, TypeHandle refined) {
00141   if (refined == TypeHandle::none()) {
00142     express_cat.error()
00143       << "Attempt to update type of " << get_void_ptr()
00144       << "(type is " << get_type()
00145       << ") to an undefined type!\n";
00146 
00147   } else if (destination == refined) {
00148     // Updating with the same type, no problem.
00149 
00150   } else if (destination.is_derived_from(refined)) {
00151     // Updating with a less-specific type, no problem.
00152 
00153   } else if (destination == TypeHandle::none() || 
00154              refined.is_derived_from(destination)) {
00155     // Updating with a more-specific type, no problem.
00156     if (express_cat.is_spam()) {
00157       express_cat.spam()
00158         << "Updating " << get_void_ptr() << " from type "
00159         << destination << " to type " << refined << "\n";
00160     }
00161     destination = refined;
00162 
00163   } else {
00164     // Unrelated types, which might or might not be a problem.
00165     express_cat.warning()
00166       << "Pointer " << get_void_ptr() << " previously indicated as type "
00167       << destination << " is now type " << refined << "!\n";
00168     return false;
00169   }
00170   
00171   return true;
00172 }
00173 
00174 #endif  // DO_MEMORY_USAGE
 All Classes Functions Variables Enumerations