Panda3D
 All Classes Functions Variables Enumerations
nodeReferenceCount.I
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 &copy) : 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 &copy) {
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 &copy) : 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 }
 All Classes Functions Variables Enumerations