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