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 ©) : 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 ©) { 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