Panda3D
 All Classes Functions Variables Enumerations
cachedTypedWritableReferenceCount.I
00001 // Filename: cachedTypedWritableReferenceCount.I
00002 // Created by:  drose (25Jan05)
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 
00016 ////////////////////////////////////////////////////////////////////
00017 //     Function: CachedTypedWritableReferenceCount::Constructor
00018 //       Access: Protected
00019 //  Description: The ReferenceCount constructor is protected because
00020 //               you almost never want to create just a ReferenceCount
00021 //               object by itself, and it's probably a mistake if you
00022 //               try.
00023 //
00024 //               ReferenceCount doesn't store any useful information
00025 //               in its own right; its only purpose is to add
00026 //               reference-counting to some other class via
00027 //               inheritance.
00028 ////////////////////////////////////////////////////////////////////
00029 INLINE CachedTypedWritableReferenceCount::
00030 CachedTypedWritableReferenceCount() {
00031   _cache_ref_count = 0;
00032 }
00033 
00034 ////////////////////////////////////////////////////////////////////
00035 //     Function: CachedTypedWritableReferenceCount::Copy Constructor
00036 //       Access: Protected
00037 //  Description: The copies of reference-counted objects do not
00038 //               themselves inherit the reference count!
00039 //
00040 //               This copy constructor is protected because you almost
00041 //               never want to create just a ReferenceCount object by
00042 //               itself, and it's probably a mistake if you try.
00043 ////////////////////////////////////////////////////////////////////
00044 INLINE CachedTypedWritableReferenceCount::
00045 CachedTypedWritableReferenceCount(const CachedTypedWritableReferenceCount &copy) : TypedWritableReferenceCount(copy) {
00046   _cache_ref_count = 0;
00047 }
00048 
00049 ////////////////////////////////////////////////////////////////////
00050 //     Function: CachedTypedWritableReferenceCount::Copy Assignment Operator
00051 //       Access: Protected
00052 //  Description: The copies of reference-counted objects do not
00053 //               themselves inherit the reference count!
00054 //
00055 //               This copy assignment operator is protected because
00056 //               you almost never want to copy just a ReferenceCount
00057 //               object by itself, and it's probably a mistake if you
00058 //               try.  Instead, this should only be called from a
00059 //               derived class that implements this operator and then
00060 //               calls up the inheritance chain.
00061 ////////////////////////////////////////////////////////////////////
00062 INLINE void CachedTypedWritableReferenceCount::
00063 operator = (const CachedTypedWritableReferenceCount &copy) {
00064   nassertv(this != NULL);
00065 
00066   // If this assertion fails, our own pointer was recently deleted.
00067   // Possibly you used a real pointer instead of a PointerTo at some
00068   // point, and the object was deleted when the PointerTo went out of
00069   // scope.  Maybe you tried to create an automatic (local variable)
00070   // instance of a class that derives from ReferenceCount.  Or maybe
00071   // your headers are out of sync, and you need to make clean in
00072   // direct or some higher tree.
00073   nassertv(_cache_ref_count != -100);
00074 
00075   TypedWritableReferenceCount::operator = (copy);
00076 }
00077 
00078 ////////////////////////////////////////////////////////////////////
00079 //     Function: CachedTypedWritableReferenceCount::Destructor
00080 //       Access: Protected
00081 //  Description: The ReferenceCount destructor is protected to
00082 //               discourage users from accidentally trying to delete a
00083 //               ReferenceCount pointer directly.  This is almost
00084 //               always a bad idea, since the destructor is not
00085 //               virtual, and you've almost certainly got some pointer
00086 //               to something that inherits from ReferenceCount, not
00087 //               just a plain old ReferenceCount object.
00088 ////////////////////////////////////////////////////////////////////
00089 INLINE CachedTypedWritableReferenceCount::
00090 ~CachedTypedWritableReferenceCount() {
00091   nassertv(this != NULL);
00092 
00093   // If this assertion fails, we're trying to delete an object that
00094   // was just deleted.  Possibly you used a real pointer instead of a
00095   // PointerTo at some point, and the object was deleted when the
00096   // PointerTo went out of scope.  Maybe you tried to create an
00097   // automatic (local variable) instance of a class that derives from
00098   // ReferenceCount.  Or maybe your headers are out of sync, and you
00099   // need to make clean in direct or some higher tree.
00100   nassertv(_cache_ref_count != -100);
00101 
00102   // If this assertion fails, the reference counts are all screwed
00103   // up altogether.  Maybe some errant code stomped all over memory
00104   // somewhere.
00105   nassertv(_cache_ref_count >= 0);
00106 
00107   // If this assertion fails, someone tried to delete this object
00108   // while its reference count was still positive.  Maybe you tried
00109   // to point a PointerTo at a static object (a local variable,
00110   // instead of one allocated via new)?  The test below against 0x7f
00111   // is supposed to check for that, but it's a pretty hokey test.
00112 
00113   // Another possibility is you inadvertently omitted a copy
00114   // constructor for a ReferenceCount object, and then bitwise
00115   // copied a dynamically allocated value--reference count and
00116   // all--onto a locally allocated one.
00117   nassertv(_cache_ref_count == 0);
00118 
00119 #ifndef NDEBUG
00120   // Ok, all clear to delete.  Now set the reference count to -100,
00121   // so we'll have a better chance of noticing if we happen to have
00122   // a stray pointer to it still out there.
00123   _cache_ref_count = -100;
00124 #endif
00125 }
00126 
00127 ////////////////////////////////////////////////////////////////////
00128 //     Function: CachedTypedWritableReferenceCount::get_cache_ref_count
00129 //       Access: Published
00130 //  Description: Returns the current reference count.
00131 ////////////////////////////////////////////////////////////////////
00132 INLINE int CachedTypedWritableReferenceCount::
00133 get_cache_ref_count() const {
00134 #ifdef _DEBUG
00135   test_ref_count_integrity();
00136 #endif
00137   return AtomicAdjust::get(_cache_ref_count);
00138 }
00139 
00140 ////////////////////////////////////////////////////////////////////
00141 //     Function: CachedTypedWritableReferenceCount::cache_ref
00142 //       Access: Published
00143 //  Description: Explicitly increments the cache reference count and
00144 //               the normal reference count simultaneously.
00145 ////////////////////////////////////////////////////////////////////
00146 INLINE void CachedTypedWritableReferenceCount::
00147 cache_ref() const {
00148 #ifdef _DEBUG
00149   nassertv(test_ref_count_integrity());
00150 #endif
00151 
00152   ref();
00153   AtomicAdjust::inc(((CachedTypedWritableReferenceCount *)this)->_cache_ref_count);
00154 }
00155 
00156 ////////////////////////////////////////////////////////////////////
00157 //     Function: CachedTypedWritableReferenceCount::cache_unref
00158 //       Access: Published
00159 //  Description: Explicitly decrements the cache reference count and
00160 //               the normal reference count simultaneously.
00161 //
00162 //               The return value is true if the new reference count
00163 //               is nonzero, false if it is zero.
00164 ////////////////////////////////////////////////////////////////////
00165 INLINE bool CachedTypedWritableReferenceCount::
00166 cache_unref() const {
00167 #ifdef _DEBUG
00168   nassertr(test_ref_count_integrity(), 0);
00169 #endif
00170 
00171   // If this assertion fails, you tried to unref an object with a
00172   // zero reference count.  Are you using ref() and unref()
00173   // directly?  Are you sure you can't use PointerTo's?
00174   nassertr(_cache_ref_count > 0, 0);
00175   
00176   AtomicAdjust::dec(((CachedTypedWritableReferenceCount *)this)->_cache_ref_count);
00177   return ReferenceCount::unref();
00178 }
00179 
00180 ////////////////////////////////////////////////////////////////////
00181 //     Function: CachedTypedWritableReferenceCount::test_ref_count_integrity
00182 //       Access: Published
00183 //  Description: Does some easy checks to make sure that the reference
00184 //               count isn't completely bogus.
00185 ////////////////////////////////////////////////////////////////////
00186 INLINE bool CachedTypedWritableReferenceCount::
00187 test_ref_count_integrity() const {
00188 #ifndef NDEBUG
00189   return do_test_ref_count_integrity();
00190 #else
00191   return true;
00192 #endif
00193 }
00194 
00195 ////////////////////////////////////////////////////////////////////
00196 //     Function: CachedTypedWritableReferenceCount::cache_unref_only
00197 //       Access: Protected
00198 //  Description: Decrements the cache reference count without affecting
00199 //               the normal reference count.  Intended to be called by
00200 //               derived classes only, presumably to reimplement
00201 //               cache_unref().
00202 ////////////////////////////////////////////////////////////////////
00203 INLINE void CachedTypedWritableReferenceCount::
00204 cache_unref_only() const {
00205 #ifdef _DEBUG
00206   nassertv(test_ref_count_integrity());
00207 #endif
00208 
00209   // If this assertion fails, you tried to unref an object with a
00210   // zero reference count.  Are you using ref() and unref()
00211   // directly?  Are you sure you can't use PointerTo's?
00212   nassertv(_cache_ref_count > 0);
00213   
00214   AtomicAdjust::dec(((CachedTypedWritableReferenceCount *)this)->_cache_ref_count);
00215 }
00216 
00217 ////////////////////////////////////////////////////////////////////
00218 //     Function: cache_unref_delete
00219 //  Description: This global helper function will unref the given
00220 //               ReferenceCount object, and if the reference count
00221 //               reaches zero, automatically delete it.  It can't be a
00222 //               member function because it's usually a bad idea to
00223 //               delete an object from within its own member function.
00224 //               It's a template function so the destructor doesn't
00225 //               have to be virtual.
00226 ////////////////////////////////////////////////////////////////////
00227 template<class RefCountType>
00228 INLINE void
00229 cache_unref_delete(RefCountType *ptr) {
00230   if (!ptr->cache_unref()) {
00231     delete ptr;
00232   }
00233 }
00234 
 All Classes Functions Variables Enumerations