Panda3D
 All Classes Functions Variables Enumerations
memoryUsagePointers.cxx
00001 // Filename: memoryUsagePointers.cxx
00002 // Created by:  drose (25May00)
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 "memoryUsagePointers.h"
00016 
00017 #ifdef DO_MEMORY_USAGE
00018 
00019 #include "config_express.h"
00020 #include "referenceCount.h"
00021 #include "typedReferenceCount.h"
00022 
00023 #ifdef HAVE_PYTHON
00024 // Pick up a few declarations so we can create Python wrappers in
00025 // get_python_pointer(), below.
00026 
00027 #include "py_panda.h"  
00028 
00029 #ifndef CPPPARSER
00030 extern EXPCL_PANDAEXPRESS Dtool_PyTypedObject Dtool_TypedObject;
00031 extern EXPCL_PANDAEXPRESS Dtool_PyTypedObject Dtool_TypedReferenceCount;
00032 extern EXPCL_PANDAEXPRESS Dtool_PyTypedObject Dtool_ReferenceCount;
00033 #endif  // CPPPARSER
00034 
00035 #endif  // HAVE_PYTHON
00036 
00037 ////////////////////////////////////////////////////////////////////
00038 //     Function: MemoryUsagePointers::Constructor
00039 //       Access: Published
00040 //  Description:
00041 ////////////////////////////////////////////////////////////////////
00042 MemoryUsagePointers::
00043 MemoryUsagePointers() {
00044 }
00045 
00046 ////////////////////////////////////////////////////////////////////
00047 //     Function: MemoryUsagePointers::Destructor
00048 //       Access: Published
00049 //  Description:
00050 ////////////////////////////////////////////////////////////////////
00051 MemoryUsagePointers::
00052 ~MemoryUsagePointers() {
00053 }
00054 
00055 ////////////////////////////////////////////////////////////////////
00056 //     Function: MemoryUsagePointers::get_num_pointers
00057 //       Access: Published
00058 //  Description: Returns the number of pointers in the set.
00059 ////////////////////////////////////////////////////////////////////
00060 int MemoryUsagePointers::
00061 get_num_pointers() const {
00062   return _entries.size();
00063 }
00064 
00065 ////////////////////////////////////////////////////////////////////
00066 //     Function: MemoryUsagePointers::get_pointer
00067 //       Access: Published
00068 //  Description: Returns the nth pointer of the set.
00069 ////////////////////////////////////////////////////////////////////
00070 ReferenceCount *MemoryUsagePointers::
00071 get_pointer(int n) const {
00072   nassertr(n >= 0 && n < get_num_pointers(), NULL);
00073   return _entries[n]._ref_ptr;
00074 }
00075 
00076 ////////////////////////////////////////////////////////////////////
00077 //     Function: MemoryUsagePointers::get_typed_pointer
00078 //       Access: Published
00079 //  Description: Returns the nth pointer of the set, typecast to a
00080 //               TypedObject if possible.  If the pointer is not a
00081 //               TypedObject or if the cast cannot be made, returns
00082 //               NULL.
00083 ////////////////////////////////////////////////////////////////////
00084 TypedObject *MemoryUsagePointers::
00085 get_typed_pointer(int n) const {
00086   nassertr(n >= 0 && n < get_num_pointers(), NULL);
00087   TypedObject *typed_ptr = _entries[n]._typed_ptr;
00088 
00089   if (typed_ptr != (TypedObject *)NULL) {
00090     return typed_ptr;
00091   }
00092 
00093   ReferenceCount *ref_ptr = _entries[n]._ref_ptr;
00094 
00095   TypeHandle type = _entries[n]._type;
00096 
00097   // We can only cast-across to a TypedObject when we explicitly know
00098   // the inheritance path.  Most of the time, this will be via
00099   // TypedReferenceCount.  There are classes defined in other packages
00100   // that inherit from TypedObject and ReferenceCount separately (like
00101   // Node), but we can't do anything about that here without knowing
00102   // about the particular class.  (Actually, we couldn't do anything
00103   // about Node anyway, because it inherits virtually from
00104   // ReferenceCount.)
00105 
00106   // RTTI can't help us here, because ReferenceCount has no virtual
00107   // functions, so we can't use C++'s new dynamic_cast feature.
00108 
00109   if (type != TypeHandle::none() &&
00110       type.is_derived_from(TypedReferenceCount::get_class_type())) {
00111     return (TypedReferenceCount *)ref_ptr;
00112   }
00113   return NULL;
00114 }
00115 
00116 ////////////////////////////////////////////////////////////////////
00117 //     Function: MemoryUsagePointers::get_type
00118 //       Access: Published
00119 //  Description: Returns the actual type of the nth pointer, if it is
00120 //               known.
00121 ////////////////////////////////////////////////////////////////////
00122 TypeHandle MemoryUsagePointers::
00123 get_type(int n) const {
00124   nassertr(n >= 0 && n < get_num_pointers(), TypeHandle::none());
00125   return _entries[n]._type;
00126 }
00127 
00128 ////////////////////////////////////////////////////////////////////
00129 //     Function: MemoryUsagePointers::get_type_name
00130 //       Access: Published
00131 //  Description: Returns the type name of the nth pointer, if it is
00132 //               known.
00133 ////////////////////////////////////////////////////////////////////
00134 string MemoryUsagePointers::
00135 get_type_name(int n) const {
00136   nassertr(n >= 0 && n < get_num_pointers(), "");
00137   return get_type(n).get_name();
00138 }
00139 
00140 ////////////////////////////////////////////////////////////////////
00141 //     Function: MemoryUsagePointers::get_age
00142 //       Access: Published
00143 //  Description: Returns the age of the nth pointer: the number of
00144 //               seconds elapsed between the time it was allocated and
00145 //               the time it was added to this set via a call to
00146 //               MemoryUsage::get_pointers().
00147 ////////////////////////////////////////////////////////////////////
00148 double MemoryUsagePointers::
00149 get_age(int n) const {
00150   nassertr(n >= 0 && n < get_num_pointers(), 0.0);
00151   return _entries[n]._age;
00152 }
00153 
00154 #ifdef HAVE_PYTHON
00155 ////////////////////////////////////////////////////////////////////
00156 //     Function: MemoryUsagePointers::get_python_pointer
00157 //       Access: Published
00158 //  Description: Returns the nth object, represented as a Python
00159 //               object of the appropriate type.  Reference counting
00160 //               will be properly set on the Python object.
00161 //
00162 //               get_typed_pointer() is almost as good as this, but
00163 //               (a) it does not set the reference count, and (b) it
00164 //               does not work for objects that do not inherit from
00165 //               TypedObject.  This will work for any object whose
00166 //               type is known, which has a Python representation.
00167 ////////////////////////////////////////////////////////////////////
00168 PyObject *MemoryUsagePointers::
00169 get_python_pointer(int n) const {
00170   nassertr(n >= 0 && n < get_num_pointers(), NULL);
00171   TypedObject *typed_ptr = _entries[n]._typed_ptr;
00172   ReferenceCount *ref_ptr = _entries[n]._ref_ptr;
00173 
00174   bool memory_rules = false;
00175   if (ref_ptr != (ReferenceCount *)NULL) {
00176     memory_rules = true;
00177     ref_ptr->ref();
00178   }
00179 
00180   if (typed_ptr != (TypedObject *)NULL) {
00181     return DTool_CreatePyInstanceTyped(typed_ptr, Dtool_TypedObject,
00182                                        memory_rules, false, 
00183                                        typed_ptr->get_type_index());
00184   }
00185 
00186   if (ref_ptr == (ReferenceCount *)NULL) {
00187     return Py_BuildValue("");
00188   }
00189 
00190   TypeHandle type = _entries[n]._type;
00191   if (type != TypeHandle::none()) {
00192     // Use TypedReferenceCount if we have it.
00193     if (type.is_derived_from(TypedReferenceCount::get_class_type())) {
00194       TypedReferenceCount *typed_ref_ptr = (TypedReferenceCount *)ref_ptr;
00195       
00196       return DTool_CreatePyInstanceTyped(typed_ref_ptr, Dtool_TypedReferenceCount,
00197                                          memory_rules, false, 
00198                                          type.get_index());
00199     }
00200 
00201     // Otherwise, trust that there is a downcast path to the actual type.
00202     return DTool_CreatePyInstanceTyped(ref_ptr, Dtool_ReferenceCount,
00203                                        memory_rules, false, 
00204                                        type.get_index());
00205   }
00206 
00207   // If worse comes to worst, just return a ReferenceCount wrapper.
00208   return DTool_CreatePyInstance(ref_ptr, Dtool_ReferenceCount, 
00209                                 memory_rules, false);
00210 }
00211 #endif
00212 
00213 ////////////////////////////////////////////////////////////////////
00214 //     Function: MemoryUsagePointers::clear
00215 //       Access: Published
00216 //  Description: Empties the set of pointers.
00217 ////////////////////////////////////////////////////////////////////
00218 void MemoryUsagePointers::
00219 clear() {
00220   _entries.clear();
00221 }
00222 
00223 ////////////////////////////////////////////////////////////////////
00224 //     Function: MemoryUsagePointers::output
00225 //       Access: Published
00226 //  Description: 
00227 ////////////////////////////////////////////////////////////////////
00228 void MemoryUsagePointers::
00229 output(ostream &out) const {
00230   out << _entries.size() << " pointers.";
00231 }
00232 
00233 ////////////////////////////////////////////////////////////////////
00234 //     Function: MemoryUsagePointers::clear
00235 //       Access: Private
00236 //  Description: Adds a new entry to the set.  Intended to be called
00237 //               only by MemoryUsage.
00238 ////////////////////////////////////////////////////////////////////
00239 void MemoryUsagePointers::
00240 add_entry(ReferenceCount *ref_ptr, TypedObject *typed_ptr,
00241           TypeHandle type, double age) {
00242   // We can't safely add pointers with a zero reference count.  They
00243   // might be statically-allocated or something, and if we try to add
00244   // them they'll try to destruct when the PointerTo later goes away.
00245   if (ref_ptr->get_ref_count() != 0) {
00246     _entries.push_back(Entry(ref_ptr, typed_ptr, type, age));
00247   }
00248 }
00249 
00250 
00251 #endif  // DO_MEMORY_USAGE
 All Classes Functions Variables Enumerations