Panda3D

referenceCount.I

00001 // Filename: referenceCount.I
00002 // Created by:  drose (23Oct98)
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 template<class Base>
00016 TypeHandle RefCountProxy<Base>::_type_handle;
00017 
00018 template<class Base>
00019 TypeHandle RefCountObj<Base>::_type_handle;
00020 
00021 ////////////////////////////////////////////////////////////////////
00022 //     Function: ReferenceCount::Constructor
00023 //       Access: Protected
00024 //  Description: The ReferenceCount constructor is protected because
00025 //               you almost never want to create just a ReferenceCount
00026 //               object by itself, and it's probably a mistake if you
00027 //               try.
00028 //
00029 //               ReferenceCount doesn't store any useful information
00030 //               in its own right; its only purpose is to add
00031 //               reference-counting to some other class via
00032 //               inheritance.
00033 ////////////////////////////////////////////////////////////////////
00034 INLINE ReferenceCount::
00035 ReferenceCount() {
00036   _weak_list = (WeakReferenceList *)NULL;
00037   _ref_count = 0;
00038 #ifdef DO_MEMORY_USAGE
00039   MemoryUsage::record_pointer(this);
00040 #endif
00041 }
00042 
00043 ////////////////////////////////////////////////////////////////////
00044 //     Function: ReferenceCount::Copy Constructor
00045 //       Access: Protected
00046 //  Description: The copies of reference-counted objects do not
00047 //               themselves inherit the reference count!
00048 //
00049 //               This copy constructor is protected because you almost
00050 //               never want to create just a ReferenceCount object by
00051 //               itself, and it's probably a mistake if you try.
00052 ////////////////////////////////////////////////////////////////////
00053 INLINE ReferenceCount::
00054 ReferenceCount(const ReferenceCount &) {
00055   _weak_list = (WeakReferenceList *)NULL;
00056   _ref_count = 0;
00057 #ifdef DO_MEMORY_USAGE
00058   MemoryUsage::record_pointer(this);
00059 #endif
00060 }
00061 
00062 ////////////////////////////////////////////////////////////////////
00063 //     Function: ReferenceCount::Copy Assignment Operator
00064 //       Access: Protected
00065 //  Description: The copies of reference-counted objects do not
00066 //               themselves inherit the reference count!
00067 //
00068 //               This copy assignment operator is protected because
00069 //               you almost never want to copy just a ReferenceCount
00070 //               object by itself, and it's probably a mistake if you
00071 //               try.  Instead, this should only be called from a
00072 //               derived class that implements this operator and then
00073 //               calls up the inheritance chain.
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   // Possibly you used a real pointer instead of a PointerTo at some
00081   // point, and the object was deleted when the PointerTo went out of
00082   // scope.  Maybe you tried to create an automatic (local variable)
00083   // instance of a class that derives from ReferenceCount.  Or maybe
00084   // your headers are out of sync, and you need to make clean in
00085   // direct or some higher tree.
00086   nassertv(_ref_count != deleted_ref_count);
00087 }
00088 
00089 ////////////////////////////////////////////////////////////////////
00090 //     Function: ReferenceCount::Destructor
00091 //       Access: Public, Virtual
00092 //  Description: 
00093 ////////////////////////////////////////////////////////////////////
00094 ReferenceCount::
00095 ~ReferenceCount() {
00096   TAU_PROFILE("ReferenceCount::~ReferenceCount()", " ", TAU_USER);
00097   nassertv(this != NULL);
00098 
00099   // If this assertion fails, we're trying to delete an object that
00100   // was just deleted.  Possibly you used a real pointer instead of a
00101   // PointerTo at some point, and the object was deleted when the
00102   // PointerTo went out of scope.  Maybe you tried to create an
00103   // automatic (local variable) instance of a class that derives from
00104   // ReferenceCount.  Or maybe your headers are out of sync, and you
00105   // need to make clean in direct or some higher tree.
00106   nassertv(_ref_count != deleted_ref_count);
00107 
00108   // If this assertion fails, we're trying to delete a static object
00109   // that still has an outstanding reference count.  You should make
00110   // sure that all references to your static objects are gone by the
00111   // time the object itself destructs.
00112   nassertv(_ref_count <= local_ref_count);
00113 
00114   // If this assertion fails, the reference counts are all screwed
00115   // up altogether.  Maybe some errant code stomped all over memory
00116   // somewhere.
00117   nassertv(_ref_count >= 0);
00118 
00119   // If this assertion fails, someone tried to delete this object
00120   // while its reference count was still positive.  Maybe you tried
00121   // to point a PointerTo at a static object (a local variable,
00122   // instead of one allocated via new)?  The test below against 0x7f
00123   // is supposed to check for that, but it's a pretty hokey test.
00124 
00125   // Another possibility is you inadvertently omitted a copy
00126   // constructor for a ReferenceCount object, and then bitwise
00127   // copied a dynamically allocated value--reference count and
00128   // all--onto a locally allocated one.
00129   nassertv(_ref_count == 0 || _ref_count == local_ref_count);
00130 
00131   // Tell our weak reference holders that we're going away now.
00132   if (_weak_list != (WeakReferenceList *)NULL) {
00133     delete (WeakReferenceList *)_weak_list;
00134     _weak_list = (WeakReferenceList *)NULL;
00135   }
00136 
00137 #ifndef NDEBUG
00138   // Ok, all clear to delete.  Now set the reference count to
00139   // deleted_ref_count, so we'll have a better chance of noticing if
00140   // we happen to have a stray pointer to it still out there.
00141   _ref_count = deleted_ref_count;
00142 #endif
00143 
00144 #ifdef DO_MEMORY_USAGE
00145   MemoryUsage::remove_pointer(this);
00146 #endif
00147 }
00148 
00149 ////////////////////////////////////////////////////////////////////
00150 //     Function: ReferenceCount::get_ref_count
00151 //       Access: Published
00152 //  Description: Returns the current reference count.
00153 ////////////////////////////////////////////////////////////////////
00154 INLINE int ReferenceCount::
00155 get_ref_count() const {
00156 #ifdef _DEBUG
00157   test_ref_count_integrity();
00158 #endif
00159   return AtomicAdjust::get(_ref_count);
00160 }
00161 
00162 ////////////////////////////////////////////////////////////////////
00163 //     Function: ReferenceCount::ref
00164 //       Access: Published
00165 //  Description: Explicitly increments the reference count.  User code
00166 //               should avoid using ref() and unref() directly, which
00167 //               can result in missed reference counts.  Instead, let
00168 //               a PointerTo object manage the reference counting
00169 //               automatically.
00170 //
00171 //               This function is const, even though it changes the
00172 //               object, because generally fiddling with an object's
00173 //               reference count isn't considered part of fiddling
00174 //               with the object.  An object might be const in other
00175 //               ways, but we still need to accurately count the
00176 //               number of references to it.
00177 ////////////////////////////////////////////////////////////////////
00178 INLINE void ReferenceCount::
00179 ref() const {
00180   TAU_PROFILE("void ReferenceCount::ref()", " ", TAU_USER);
00181 #ifdef _DEBUG
00182   nassertv(test_ref_count_integrity());
00183 #endif
00184 
00185   AtomicAdjust::inc(((ReferenceCount *)this)->_ref_count);
00186 }
00187 
00188 ////////////////////////////////////////////////////////////////////
00189 //     Function: ReferenceCount::unref
00190 //       Access: Published, Virtual
00191 //  Description: Explicitly decrements the reference count.  Note that
00192 //               the object will not be implicitly deleted by unref()
00193 //               simply because the reference count drops to zero.
00194 //               (Having a member function delete itself is
00195 //               problematic.) However, see the helper function
00196 //               unref_delete().
00197 //
00198 //               User code should avoid using ref() and unref()
00199 //               directly, which can result in missed reference
00200 //               counts.  Instead, let a PointerTo object manage the
00201 //               reference counting automatically.
00202 //
00203 //               This function is const, even though it changes the
00204 //               object, because generally fiddling with an object's
00205 //               reference count isn't considered part of fiddling
00206 //               with the object.  An object might be const in other
00207 //               ways, but we still need to accurately count the
00208 //               number of references to it.
00209 //
00210 //               The return value is true if the new reference count
00211 //               is nonzero, false if it is zero.
00212 ////////////////////////////////////////////////////////////////////
00213 INLINE bool ReferenceCount::
00214 unref() const {
00215   TAU_PROFILE("void ReferenceCount::unref()", " ", TAU_USER);
00216 #ifdef _DEBUG
00217   nassertr(test_ref_count_integrity(), 0);
00218 
00219   // If this assertion fails, you tried to unref an object with a
00220   // zero reference count.  Are you using ref() and unref()
00221   // directly?  Are you sure you can't use PointerTo's?
00222   nassertr(_ref_count > 0, 0);
00223 #endif
00224   return AtomicAdjust::dec(((ReferenceCount *)this)->_ref_count);
00225 }
00226 
00227 
00228 ////////////////////////////////////////////////////////////////////
00229 //     Function: ReferenceCount::test_ref_count_integrity
00230 //       Access: Published
00231 //  Description: Does some easy checks to make sure that the reference
00232 //               count isn't completely bogus.  Returns true if ok,
00233 //               false otherwise.
00234 ////////////////////////////////////////////////////////////////////
00235 INLINE bool ReferenceCount::
00236 test_ref_count_integrity() const {
00237 #ifndef NDEBUG
00238   return do_test_ref_count_integrity();
00239 #else
00240   return true;
00241 #endif
00242 }
00243 
00244 ////////////////////////////////////////////////////////////////////
00245 //     Function: ReferenceCount::test_ref_count_nonzero
00246 //       Access: Published
00247 //  Description: Does some easy checks to make sure that the reference
00248 //               count isn't zero, or completely bogus.  Returns true
00249 //               if ok, false otherwise.
00250 ////////////////////////////////////////////////////////////////////
00251 INLINE bool ReferenceCount::
00252 test_ref_count_nonzero() const {
00253 #ifndef NDEBUG
00254   return do_test_ref_count_nonzero();
00255 #else
00256   return true;
00257 #endif
00258 }
00259 
00260 ////////////////////////////////////////////////////////////////////
00261 //     Function: ReferenceCount::local_object
00262 //       Access: Public
00263 //  Description: This function should be called, once, immediately
00264 //               after creating a new instance of some
00265 //               ReferenceCount-derived object on the stack.
00266 //
00267 //               This allows the object to be passed to functions that
00268 //               will increment and decrement the object's reference
00269 //               count temporarily, and it will prevent the object
00270 //               from being deleted (inappropriately), when the
00271 //               reference count returns to zero.  It actually
00272 //               achieves this by setting a large positive value in
00273 //               the reference count field.
00274 ////////////////////////////////////////////////////////////////////
00275 INLINE void ReferenceCount::
00276 local_object() {
00277   // If this assertion fails, you didn't call this immediately after
00278   // creating a local object.
00279   nassertv(_ref_count == 0);
00280 
00281   _ref_count = local_ref_count;
00282 }
00283 
00284 ////////////////////////////////////////////////////////////////////
00285 //     Function: ReferenceCount::has_weak_list
00286 //       Access: Public
00287 //  Description: Returns true if this particular ReferenceCount object
00288 //               has a WeakReferenceList created, false otherwise.  In
00289 //               general, this will be true if there was ever a
00290 //               WeakPointerTo created for this object (even if there
00291 //               is not any for it now).
00292 ////////////////////////////////////////////////////////////////////
00293 INLINE bool ReferenceCount::
00294 has_weak_list() const {
00295   return _weak_list != (WeakReferenceList *)NULL;
00296 }
00297 
00298 ////////////////////////////////////////////////////////////////////
00299 //     Function: ReferenceCount::get_weak_list
00300 //       Access: Public
00301 //  Description: Returns the WeakReferenceList associated with this
00302 //               ReferenceCount object.  If there has never been a
00303 //               WeakReferenceList associated with this object,
00304 //               creates one now.
00305 ////////////////////////////////////////////////////////////////////
00306 INLINE WeakReferenceList *ReferenceCount::
00307 get_weak_list() const {
00308   if (AtomicAdjust::get_ptr(_weak_list) == (WeakReferenceList *)NULL) {
00309     ((ReferenceCount *)this)->create_weak_list();
00310   }
00311   return (WeakReferenceList *)AtomicAdjust::get_ptr(_weak_list);
00312 }
00313 
00314 ////////////////////////////////////////////////////////////////////
00315 //     Function: ReferenceCount::weak_ref
00316 //       Access: Public
00317 //  Description: Adds the indicated PointerToVoid as a weak reference
00318 //               to this object.
00319 ////////////////////////////////////////////////////////////////////
00320 INLINE void ReferenceCount::
00321 weak_ref(WeakPointerToVoid *ptv) {
00322   TAU_PROFILE("void ReferenceCount::weak_ref()", " ", TAU_USER);
00323   get_weak_list()->add_reference(ptv);
00324 }
00325 
00326 ////////////////////////////////////////////////////////////////////
00327 //     Function: ReferenceCount::weak_unref
00328 //       Access: Public
00329 //  Description: Removes the indicated PointerToVoid as a weak reference
00330 //               to this object.  It must have previously been added
00331 //               via a call to weak_ref().
00332 ////////////////////////////////////////////////////////////////////
00333 INLINE void ReferenceCount::
00334 weak_unref(WeakPointerToVoid *ptv) {
00335   TAU_PROFILE("void ReferenceCount::weak_unref()", " ", TAU_USER);
00336   nassertv(has_weak_list());
00337   ((WeakReferenceList *)_weak_list)->clear_reference(ptv);
00338 }
00339 
00340 ////////////////////////////////////////////////////////////////////
00341 //     Function: unref_delete
00342 //  Description: This global helper function will unref the given
00343 //               ReferenceCount object, and if the reference count
00344 //               reaches zero, automatically delete it.  It can't be a
00345 //               member function because it's usually a bad idea to
00346 //               delete an object from within its own member function.
00347 //               It's a template function so the destructor doesn't
00348 //               have to be virtual.
00349 ////////////////////////////////////////////////////////////////////
00350 template<class RefCountType>
00351 INLINE void
00352 unref_delete(RefCountType *ptr) {
00353   TAU_PROFILE("void unref_delete(RefCountType *)", " ", TAU_USER);
00354   // Although it may be tempting to try to upcast ptr to a
00355   // ReferenceCount object (particularly to get around inheritance
00356   // issues), resist that temptation, since some classes (in
00357   // particular, TransformState and RenderState) rely on a non-virtual
00358   // overloading of the unref() method.
00359 
00360   if (!ptr->unref()) {
00361     // If the reference count has gone to zero, delete the object.
00362     delete ptr;
00363   } 
00364 }
00365 
00366 ////////////////////////////////////////////////////////////////////
00367 //     Function: RefCountProxy::Constructor
00368 //       Access: Public
00369 //  Description:
00370 ////////////////////////////////////////////////////////////////////
00371 template<class Base>
00372 INLINE RefCountProxy<Base>::
00373 RefCountProxy() {
00374 }
00375 
00376 ////////////////////////////////////////////////////////////////////
00377 //     Function: RefCountProxy::Copy Constructor
00378 //       Access: Public
00379 //  Description:
00380 ////////////////////////////////////////////////////////////////////
00381 template<class Base>
00382 INLINE RefCountProxy<Base>::
00383 RefCountProxy(const Base &copy) : _base(copy) {
00384 }
00385 
00386 ////////////////////////////////////////////////////////////////////
00387 //     Function: RefCountProxy::Base Typecast Operator
00388 //       Access: Public
00389 //  Description:
00390 ////////////////////////////////////////////////////////////////////
00391 template<class Base>
00392 INLINE RefCountProxy<Base>::
00393 operator Base &() {
00394   return _base;
00395 }
00396 
00397 ////////////////////////////////////////////////////////////////////
00398 //     Function: RefCountProxy::Base Typecast Operator
00399 //       Access: Public
00400 //  Description:
00401 ////////////////////////////////////////////////////////////////////
00402 template<class Base>
00403 INLINE RefCountProxy<Base>::
00404 operator const Base &() const {
00405   return _base;
00406 }
00407 
00408 ////////////////////////////////////////////////////////////////////
00409 //     Function: RefCountProxy::init_type
00410 //       Access: Public
00411 //  Description:
00412 ////////////////////////////////////////////////////////////////////
00413 template<class Base>
00414 void RefCountProxy<Base>::
00415 init_type() {
00416   do_init_type(Base);
00417   register_type(_type_handle,
00418                 "RefCountProxy<" + get_type_handle(Base).get_name() + ">",
00419                 get_type_handle(Base));
00420 }
00421 
00422 
00423 ////////////////////////////////////////////////////////////////////
00424 //     Function: RefCountObj::Constructor
00425 //       Access: Public
00426 //  Description:
00427 ////////////////////////////////////////////////////////////////////
00428 template<class Base>
00429 INLINE RefCountObj<Base>::
00430 RefCountObj() {
00431 }
00432 
00433 ////////////////////////////////////////////////////////////////////
00434 //     Function: RefCountObj::Copy Constructor
00435 //       Access: Public
00436 //  Description:
00437 ////////////////////////////////////////////////////////////////////
00438 template<class Base>
00439 INLINE RefCountObj<Base>::
00440 RefCountObj(const Base &copy) : Base(copy) {
00441 }
00442 
00443 
00444 ////////////////////////////////////////////////////////////////////
00445 //     Function: RefCountObj::init_type
00446 //       Access: Public
00447 //  Description:
00448 ////////////////////////////////////////////////////////////////////
00449 template<class Base>
00450 void RefCountObj<Base>::
00451 init_type() {
00452 #if defined(HAVE_RTTI) && !defined(__EDG__)
00453   // If we have RTTI, we can determine the name of the base type.
00454   string base_name = typeid(Base).name();
00455 #else
00456   string base_name = "unknown";
00457 #endif
00458 
00459   TypeHandle base_type = register_dynamic_type(base_name);
00460 
00461   ReferenceCount::init_type();
00462   _type_handle =
00463     register_dynamic_type("RefCountObj<" + base_name + ">",
00464                           base_type, ReferenceCount::get_class_type());
00465 }
 All Classes Functions Variables Enumerations