Panda3D
|
00001 // Filename: nodeReferenceCount.I 00002 // Created by: drose (01May06) 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 template<class Base> 00017 TypeHandle NodeRefCountObj<Base>::_type_handle; 00018 00019 //////////////////////////////////////////////////////////////////// 00020 // Function: NodeReferenceCount::Constructor 00021 // Access: Protected 00022 // Description: The ReferenceCount constructor is protected because 00023 // you almost never want to create just a ReferenceCount 00024 // object by itself, and it's probably a mistake if you 00025 // try. 00026 // 00027 // ReferenceCount doesn't store any useful information 00028 // in its own right; its only purpose is to add 00029 // reference-counting to some other class via 00030 // inheritance. 00031 //////////////////////////////////////////////////////////////////// 00032 INLINE NodeReferenceCount:: 00033 NodeReferenceCount() { 00034 _node_ref_count = 0; 00035 } 00036 00037 //////////////////////////////////////////////////////////////////// 00038 // Function: NodeReferenceCount::Copy Constructor 00039 // Access: Protected 00040 // Description: The copies of reference-counted objects do not 00041 // themselves inherit the reference count! 00042 // 00043 // This copy constructor is protected because you almost 00044 // never want to create just a ReferenceCount object by 00045 // itself, and it's probably a mistake if you try. 00046 //////////////////////////////////////////////////////////////////// 00047 INLINE NodeReferenceCount:: 00048 NodeReferenceCount(const NodeReferenceCount ©) : ReferenceCount(copy) { 00049 _node_ref_count = 0; 00050 } 00051 00052 //////////////////////////////////////////////////////////////////// 00053 // Function: NodeReferenceCount::Copy Assignment Operator 00054 // Access: Protected 00055 // Description: The copies of reference-counted objects do not 00056 // themselves inherit the reference count! 00057 // 00058 // This copy assignment operator is protected because 00059 // you almost never want to copy just a ReferenceCount 00060 // object by itself, and it's probably a mistake if you 00061 // try. Instead, this should only be called from a 00062 // derived class that implements this operator and then 00063 // calls up the inheritance chain. 00064 //////////////////////////////////////////////////////////////////// 00065 INLINE void NodeReferenceCount:: 00066 operator = (const NodeReferenceCount ©) { 00067 nassertv(this != NULL); 00068 00069 // If this assertion fails, our own pointer was recently deleted. 00070 // Possibly you used a real pointer instead of a PointerTo at some 00071 // point, and the object was deleted when the PointerTo went out of 00072 // scope. Maybe you tried to create an automatic (local variable) 00073 // instance of a class that derives from ReferenceCount. Or maybe 00074 // your headers are out of sync, and you need to make clean in 00075 // direct or some higher tree. 00076 nassertv(_node_ref_count != -100); 00077 00078 ReferenceCount::operator = (copy); 00079 } 00080 00081 //////////////////////////////////////////////////////////////////// 00082 // Function: NodeReferenceCount::Destructor 00083 // Access: Protected 00084 // Description: The ReferenceCount destructor is protected to 00085 // discourage users from accidentally trying to delete a 00086 // ReferenceCount pointer directly. This is almost 00087 // always a bad idea, since the destructor is not 00088 // virtual, and you've almost certainly got some pointer 00089 // to something that inherits from ReferenceCount, not 00090 // just a plain old ReferenceCount object. 00091 //////////////////////////////////////////////////////////////////// 00092 INLINE NodeReferenceCount:: 00093 ~NodeReferenceCount() { 00094 nassertv(this != NULL); 00095 00096 // If this assertion fails, we're trying to delete an object that 00097 // was just deleted. Possibly you used a real pointer instead of a 00098 // PointerTo at some point, and the object was deleted when the 00099 // PointerTo went out of scope. Maybe you tried to create an 00100 // automatic (local variable) instance of a class that derives from 00101 // ReferenceCount. Or maybe your headers are out of sync, and you 00102 // need to make clean in direct or some higher tree. 00103 nassertv(_node_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(_node_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(_node_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 _node_ref_count = -100; 00127 #endif 00128 } 00129 00130 //////////////////////////////////////////////////////////////////// 00131 // Function: NodeReferenceCount::get_node_ref_count 00132 // Access: Published 00133 // Description: Returns the current reference count. 00134 //////////////////////////////////////////////////////////////////// 00135 INLINE int NodeReferenceCount:: 00136 get_node_ref_count() const { 00137 #ifdef _DEBUG 00138 test_ref_count_integrity(); 00139 #endif 00140 return AtomicAdjust::get(_node_ref_count); 00141 } 00142 00143 //////////////////////////////////////////////////////////////////// 00144 // Function: NodeReferenceCount::node_ref 00145 // Access: Published 00146 // Description: Explicitly increments the node reference count and 00147 // the normal reference count simultaneously. 00148 //////////////////////////////////////////////////////////////////// 00149 INLINE void NodeReferenceCount:: 00150 node_ref() const { 00151 #ifdef _DEBUG 00152 nassertv(test_ref_count_integrity()); 00153 #endif 00154 00155 ref(); 00156 AtomicAdjust::inc(((NodeReferenceCount *)this)->_node_ref_count); 00157 } 00158 00159 //////////////////////////////////////////////////////////////////// 00160 // Function: NodeReferenceCount::node_unref 00161 // Access: Published 00162 // Description: Explicitly decrements the node reference count and 00163 // the normal reference count simultaneously. 00164 // 00165 // The return value is true if the new reference count 00166 // is nonzero, false if it is zero. 00167 //////////////////////////////////////////////////////////////////// 00168 INLINE bool NodeReferenceCount:: 00169 node_unref() const { 00170 node_unref_only(); 00171 return unref(); 00172 } 00173 00174 //////////////////////////////////////////////////////////////////// 00175 // Function: NodeReferenceCount::test_ref_count_integrity 00176 // Access: Published 00177 // Description: Does some easy checks to make sure that the reference 00178 // count isn't completely bogus. 00179 //////////////////////////////////////////////////////////////////// 00180 INLINE bool NodeReferenceCount:: 00181 test_ref_count_integrity() const { 00182 #ifndef NDEBUG 00183 return do_test_ref_count_integrity(); 00184 #else 00185 return true; 00186 #endif 00187 } 00188 00189 //////////////////////////////////////////////////////////////////// 00190 // Function: NodeReferenceCount::node_unref_only 00191 // Access: Protected 00192 // Description: Decrements the node reference count without affecting 00193 // the normal reference count. Intended to be called by 00194 // derived classes only, presumably to reimplement 00195 // node_unref(). 00196 //////////////////////////////////////////////////////////////////// 00197 INLINE void NodeReferenceCount:: 00198 node_unref_only() const { 00199 #ifdef _DEBUG 00200 nassertv(test_ref_count_integrity()); 00201 #endif 00202 00203 // If this assertion fails, you tried to unref an object with a 00204 // zero reference count. Are you using ref() and unref() 00205 // directly? Are you sure you can't use PointerTo's? 00206 nassertv(_node_ref_count > 0); 00207 00208 AtomicAdjust::dec(((NodeReferenceCount *)this)->_node_ref_count); 00209 } 00210 00211 //////////////////////////////////////////////////////////////////// 00212 // Function: node_unref_delete 00213 // Description: This global helper function will unref the given 00214 // ReferenceCount object, and if the reference count 00215 // reaches zero, automatically delete it. It can't be a 00216 // member function because it's usually a bad idea to 00217 // delete an object from within its own member function. 00218 // It's a template function so the destructor doesn't 00219 // have to be virtual. 00220 //////////////////////////////////////////////////////////////////// 00221 template<class RefCountType> 00222 INLINE void 00223 node_unref_delete(RefCountType *ptr) { 00224 if (!ptr->node_unref()) { 00225 delete ptr; 00226 } 00227 } 00228 00229 00230 00231 //////////////////////////////////////////////////////////////////// 00232 // Function: NodeRefCountObj::Constructor 00233 // Access: Public 00234 // Description: 00235 //////////////////////////////////////////////////////////////////// 00236 template<class Base> 00237 INLINE NodeRefCountObj<Base>:: 00238 NodeRefCountObj() { 00239 } 00240 00241 //////////////////////////////////////////////////////////////////// 00242 // Function: NodeRefCountObj::Copy Constructor 00243 // Access: Public 00244 // Description: 00245 //////////////////////////////////////////////////////////////////// 00246 template<class Base> 00247 INLINE NodeRefCountObj<Base>:: 00248 NodeRefCountObj(const Base ©) : Base(copy) { 00249 } 00250 00251 00252 //////////////////////////////////////////////////////////////////// 00253 // Function: NodeRefCountObj::init_type 00254 // Access: Public 00255 // Description: 00256 //////////////////////////////////////////////////////////////////// 00257 template<class Base> 00258 void NodeRefCountObj<Base>:: 00259 init_type() { 00260 #if defined(HAVE_RTTI) && !defined(__EDG__) 00261 // If we have RTTI, we can determine the name of the base type. 00262 string base_name = typeid(Base).name(); 00263 #else 00264 string base_name = "unknown"; 00265 #endif 00266 00267 TypeHandle base_type = register_dynamic_type(base_name); 00268 00269 ReferenceCount::init_type(); 00270 _type_handle = 00271 register_dynamic_type("NodeRefCountObj<" + base_name + ">", 00272 base_type, ReferenceCount::get_class_type()); 00273 }