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 ©) : _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 ©) : 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 }