Main Page   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members  

panda/src/express/referenceCount.I

Go to the documentation of this file.
00001 // Filename: referenceCount.I
00002 // Created by:  drose (23Oct98)
00003 //
00004 ////////////////////////////////////////////////////////////////////
00005 //
00006 // PANDA 3D SOFTWARE
00007 // Copyright (c) 2001, Disney Enterprises, Inc.  All rights reserved
00008 //
00009 // All use of this software is subject to the terms of the Panda 3d
00010 // Software license.  You should have received a copy of this license
00011 // along with this source code; you will also find a current copy of
00012 // the license at http://www.panda3d.org/license.txt .
00013 //
00014 // To contact the maintainers of this program write to
00015 // panda3d@yahoogroups.com .
00016 //
00017 ////////////////////////////////////////////////////////////////////
00018 
00019 template<class Base>
00020 TypeHandle RefCountProxy<Base>::_type_handle;
00021 
00022 template<class Base>
00023 TypeHandle RefCountObj<Base>::_type_handle;
00024 
00025 ////////////////////////////////////////////////////////////////////
00026 //     Function: ReferenceCount::Constructor
00027 //       Access: Protected
00028 //  Description: The ReferenceCount constructor is protected because
00029 //               you almost never want to create just a ReferenceCount
00030 //               object by itself, and it's probably a mistake if you
00031 //               try.
00032 //
00033 //               ReferenceCount doesn't store any useful information
00034 //               in its own right; its only purpose is to add
00035 //               reference-counting to some other class via
00036 //               inheritance.
00037 ////////////////////////////////////////////////////////////////////
00038 INLINE ReferenceCount::
00039 ReferenceCount() {
00040   _ref_count = 0;
00041 #ifdef DO_MEMORY_USAGE
00042   MemoryUsage::record_pointer(this);
00043 #endif
00044 }
00045 
00046 ////////////////////////////////////////////////////////////////////
00047 //     Function: ReferenceCount::Copy Constructor
00048 //       Access: Protected
00049 //  Description: The copies of reference-counted objects do not
00050 //               themselves inherit the reference count!
00051 //
00052 //               This copy constructor is protected because you almost
00053 //               never want to create just a ReferenceCount object by
00054 //               itself, and it's probably a mistake if you try.
00055 ////////////////////////////////////////////////////////////////////
00056 INLINE ReferenceCount::
00057 ReferenceCount(const ReferenceCount &) {
00058   _ref_count = 0;
00059 #ifdef DO_MEMORY_USAGE
00060   MemoryUsage::record_pointer(this);
00061 #endif
00062 }
00063 
00064 ////////////////////////////////////////////////////////////////////
00065 //     Function: ReferenceCount::Copy Assignment Operator
00066 //       Access: Protected
00067 //  Description: The copies of reference-counted objects do not
00068 //               themselves inherit the reference count!
00069 //
00070 //               This copy assignment operator is protected because
00071 //               you almost never want to copy just a ReferenceCount
00072 //               object by itself, and it's probably a mistake if you
00073 //               try.
00074 ////////////////////////////////////////////////////////////////////
00075 INLINE void ReferenceCount::
00076 operator = (const ReferenceCount &) {
00077   nassertv(this != NULL);
00078 
00079   // If this assertion fails, our own pointer was recently deleted.
00080   // Yikes!
00081   nassertv(_ref_count != -100);
00082 }
00083 
00084 ////////////////////////////////////////////////////////////////////
00085 //     Function: ReferenceCount::Destructor
00086 //       Access: Protected
00087 //  Description: The ReferenceCount destructor is protected to
00088 //               discourage users from accidentally trying to delete a
00089 //               ReferenceCount pointer directly.  This is almost
00090 //               always a bad idea, since the destructor is not
00091 //               virtual, and you've almost certainly got some pointer
00092 //               to something that inherits from ReferenceCount, not
00093 //               just a plain old ReferenceCount object.
00094 ////////////////////////////////////////////////////////////////////
00095 INLINE ReferenceCount::
00096 ~ReferenceCount() {
00097   nassertv(this != NULL);
00098 
00099   // If this assertion fails, we're trying to delete an object that
00100   // was just deleted.  Probably you've accidentally made a bitwise
00101   // copy of a PointerTo, by forgetting to write a copy constructor
00102   // for a class that contains PointerTo's.
00103   nassertv(_ref_count != -100);
00104 
00105   // If this assertion fails, the reference counts are all screwed
00106   // up altogether.  Maybe some errant code stomped all over memory
00107   // somewhere.
00108   nassertv(_ref_count >= 0);
00109 
00110   // If this assertion fails, someone tried to delete this object
00111   // while its reference count was still positive.  Maybe you tried
00112   // to point a PointerTo at a static object (a local variable,
00113   // instead of one allocated via new)?  The test below against 0x7f
00114   // is supposed to check for that, but it's a pretty hokey test.
00115 
00116   // Another possibility is you inadvertently omitted a copy
00117   // constructor for a ReferenceCount object, and then bitwise
00118   // copied a dynamically allocated value--reference count and
00119   // all--onto a locally allocated one.
00120   nassertv(_ref_count == 0);
00121 
00122 #ifndef NDEBUG
00123   // Ok, all clear to delete.  Now set the reference count to -100,
00124   // so we'll have a better chance of noticing if we happen to have
00125   // a stray pointer to it still out there.
00126   _ref_count = -100;
00127 #endif
00128 
00129 #ifdef DO_MEMORY_USAGE
00130   MemoryUsage::remove_pointer(this);
00131 #endif
00132 }
00133 
00134 ////////////////////////////////////////////////////////////////////
00135 //     Function: ReferenceCount::get_ref_count
00136 //       Access: Public
00137 //  Description: Returns the current reference count.
00138 ////////////////////////////////////////////////////////////////////
00139 INLINE int ReferenceCount::
00140 get_ref_count() const {
00141 #ifndef NDEBUG
00142   test_ref_count_integrity();
00143 #endif
00144   return _ref_count;
00145 }
00146 
00147 ////////////////////////////////////////////////////////////////////
00148 //     Function: ReferenceCount::ref
00149 //       Access: Public
00150 //  Description: Explicitly increments the reference count.  User code
00151 //               should avoid using ref() and unref() directly, which
00152 //               can result in missed reference counts.  Instead, let
00153 //               a PointerTo object manage the reference counting
00154 //               automatically.
00155 //
00156 //               This function is const, even though it changes the
00157 //               object, because generally fiddling with an object's
00158 //               reference count isn't considered part of fiddling
00159 //               with the object.  An object might be const in other
00160 //               ways, but we still need to accurately count the
00161 //               number of references to it.
00162 //
00163 //               The return value is the new reference count.
00164 ////////////////////////////////////////////////////////////////////
00165 INLINE int ReferenceCount::
00166 ref() const {
00167   nassertr(this != NULL, 0);
00168 
00169   // If this assertion fails, we're trying to ref a pointer that was
00170   // just deleted.  Probably you used a real pointer instead of a
00171   // PointerTo at some point, and the object was deleted when the
00172   // PointerTo went out of scope.  Either that, or you forgot to
00173   // define a copy constructor for a class that contains
00174   // PointerTo's.
00175   nassertr(_ref_count != -100, 0);
00176 
00177   // If this assertion fails, the reference counts are all screwed
00178   // up altogether.  Maybe some errant code stomped all over memory
00179   // somewhere.
00180   nassertr(_ref_count >= 0, 0);
00181 
00182   return AtomicAdjust::inc(((ReferenceCount *)this)->_ref_count);
00183 }
00184 
00185 ////////////////////////////////////////////////////////////////////
00186 //     Function: ReferenceCount::unref
00187 //       Access: Public
00188 //  Description: Explicitly decrements the reference count.  Note that
00189 //               the object will not be implicitly deleted by unref()
00190 //               simply because the reference count drops to zero.
00191 //               (Having a member function delete itself is
00192 //               problematic; plus, we don't have a virtual destructor
00193 //               anyway.) However, see the helper function
00194 //               unref_delete().
00195 //
00196 //               User code should avoid using ref() and unref()
00197 //               directly, which can result in missed reference
00198 //               counts.  Instead, let a PointerTo object manage the
00199 //               reference counting automatically.
00200 //
00201 //               This function is const, even though it changes the
00202 //               object, because generally fiddling with an object's
00203 //               reference count isn't considered part of fiddling
00204 //               with the object.  An object might be const in other
00205 //               ways, but we still need to accurately count the
00206 //               number of references to it.
00207 //
00208 //               The return value is the new reference count.
00209 ////////////////////////////////////////////////////////////////////
00210 INLINE int ReferenceCount::
00211 unref() const {
00212   nassertr(this != NULL, false);
00213 
00214   // If this assertion fails, we're trying to unref a pointer that
00215   // was just deleted.  Probably you used a real pointer instead of
00216   // a PointerTo at some point, and the object was deleted when the
00217   // PointerTo went out of scope.  Either that, or you forgot to
00218   // define a copy constructor for a class that contains
00219   // PointerTo's.
00220   nassertr(_ref_count != -100, false);
00221 
00222   // If this assertion fails, the reference counts are all screwed
00223   // up altogether.  Maybe some errant code stomped all over memory
00224   // somewhere.
00225   nassertr(_ref_count >= 0, false);
00226 
00227   // If this assertion fails, you tried to unref an object with a
00228   // zero reference count.  Are you using ref() and unref()
00229   // directly?  Are you sure you can't use PointerTo's?
00230   nassertr(_ref_count > 0, false);
00231   return AtomicAdjust::dec(((ReferenceCount *)this)->_ref_count);
00232 }
00233 
00234 
00235 ////////////////////////////////////////////////////////////////////
00236 //     Function: ReferenceCount::test_ref_count_integrity
00237 //       Access: Public
00238 //  Description: Does some easy checks to make sure that the reference
00239 //               count isn't completely bogus.
00240 ////////////////////////////////////////////////////////////////////
00241 INLINE void ReferenceCount::
00242 test_ref_count_integrity() const {
00243 #ifndef NDEBUG
00244   nassertv(this != NULL);
00245 
00246   // If this assertion fails, we're trying to access a pointer that
00247   // was just deleted.  Probably you used a real pointer instead of
00248   // a PointerTo at some point, and the object was deleted when the
00249   // PointerTo went out of scope.  Either that, or you forgot to
00250   // define a copy constructor for a class that contains
00251   // PointerTo's.
00252   nassertv(_ref_count != -100);
00253 
00254   // If this assertion fails, the reference counts are all screwed
00255   // up altogether.  Maybe some errant code stomped all over memory
00256   // somewhere.
00257   nassertv(_ref_count >= 0);
00258 #endif
00259 }
00260 
00261 ////////////////////////////////////////////////////////////////////
00262 //     Function: unref_delete
00263 //  Description: This global helper function will unref the given
00264 //               ReferenceCount object, and if the reference count
00265 //               reaches zero, automatically delete it.  It can't be a
00266 //               member function because it's usually a bad idea to
00267 //               delete an object from within its own member function.
00268 //               It's a template function so the destructor doesn't
00269 //               have to be virtual.
00270 ////////////////////////////////////////////////////////////////////
00271 template<class RefCountType>
00272 INLINE void
00273 unref_delete(RefCountType *ptr) {
00274   if (((ReferenceCount *)ptr)->unref() == 0) {
00275 #ifndef NDEBUG
00276     if (get_leak_memory()) {
00277       // In leak-memory mode, we don't actually delete the pointer,
00278       // although we do call the destructor explicitly.  This has
00279       // exactly the same effect as deleting it, without actually
00280       // freeing up the memory it uses.
00281 
00282       // Furthermore, if we have never-destruct set, we don't even
00283       // call the destructor.
00284       if (!get_never_destruct()) {
00285         ptr->~RefCountType();
00286       }
00287       return;
00288     }
00289 #endif
00290     delete ptr;
00291   }
00292 }
00293 
00294 
00295 ////////////////////////////////////////////////////////////////////
00296 //     Function: RefCountProxy::Constructor
00297 //       Access: Public
00298 //  Description:
00299 ////////////////////////////////////////////////////////////////////
00300 template<class Base>
00301 INLINE RefCountProxy<Base>::
00302 RefCountProxy() {
00303 }
00304 
00305 ////////////////////////////////////////////////////////////////////
00306 //     Function: RefCountProxy::Copy Constructor
00307 //       Access: Public
00308 //  Description:
00309 ////////////////////////////////////////////////////////////////////
00310 template<class Base>
00311 INLINE RefCountProxy<Base>::
00312 RefCountProxy(const Base &copy) : _base(copy) {
00313 }
00314 
00315 ////////////////////////////////////////////////////////////////////
00316 //     Function: RefCountProxy::Base Typecast Operator
00317 //       Access: Public
00318 //  Description:
00319 ////////////////////////////////////////////////////////////////////
00320 template<class Base>
00321 INLINE RefCountProxy<Base>::
00322 operator Base &() {
00323   return _base;
00324 }
00325 
00326 ////////////////////////////////////////////////////////////////////
00327 //     Function: RefCountProxy::Base Typecast Operator
00328 //       Access: Public
00329 //  Description:
00330 ////////////////////////////////////////////////////////////////////
00331 template<class Base>
00332 INLINE RefCountProxy<Base>::
00333 operator const Base &() const {
00334   return _base;
00335 }
00336 
00337 ////////////////////////////////////////////////////////////////////
00338 //     Function: RefCountProxy::init_type
00339 //       Access: Public
00340 //  Description:
00341 ////////////////////////////////////////////////////////////////////
00342 template<class Base>
00343 void RefCountProxy<Base>::
00344 init_type() {
00345   do_init_type(Base);
00346   register_type(_type_handle,
00347                 "RefCountProxy<" + get_type_handle(Base).get_name() + ">",
00348                 get_type_handle(Base));
00349 }
00350 
00351 
00352 ////////////////////////////////////////////////////////////////////
00353 //     Function: RefCountObj::Constructor
00354 //       Access: Public
00355 //  Description:
00356 ////////////////////////////////////////////////////////////////////
00357 template<class Base>
00358 INLINE RefCountObj<Base>::
00359 RefCountObj() {
00360 }
00361 
00362 ////////////////////////////////////////////////////////////////////
00363 //     Function: RefCountObj::Copy Constructor
00364 //       Access: Public
00365 //  Description:
00366 ////////////////////////////////////////////////////////////////////
00367 template<class Base>
00368 INLINE RefCountObj<Base>::
00369 RefCountObj(const Base &copy) : Base(copy) {
00370 }
00371 
00372 
00373 ////////////////////////////////////////////////////////////////////
00374 //     Function: RefCountObj::init_type
00375 //       Access: Public
00376 //  Description:
00377 ////////////////////////////////////////////////////////////////////
00378 template<class Base>
00379 void RefCountObj<Base>::
00380 init_type() {
00381 #ifdef HAVE_RTTI
00382   // If we have RTTI, we can determine the name of the base type.
00383   string base_name = typeid(Base).name();
00384 #else
00385   string base_name = "unknown";
00386 #endif
00387 
00388   TypeHandle base_type = register_dynamic_type(base_name);
00389 
00390   ReferenceCount::init_type();
00391   _type_handle =
00392     register_dynamic_type("RefCountObj<" + base_name + ">",
00393                           base_type, ReferenceCount::get_class_type());
00394 }

Generated on Fri May 2 00:38:34 2003 for Panda by doxygen1.3