Panda3D
 All Classes Functions Variables Enumerations
nodeCachedReferenceCount.I
00001 // Filename: nodeCachedReferenceCount.I
00002 // Created by:  drose (07May05)
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: NodeCachedReferenceCount::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 NodeCachedReferenceCount::
00030 NodeCachedReferenceCount() {
00031   _node_ref_count = 0;
00032 }
00033 
00034 ////////////////////////////////////////////////////////////////////
00035 //     Function: NodeCachedReferenceCount::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 NodeCachedReferenceCount::
00045 NodeCachedReferenceCount(const NodeCachedReferenceCount &copy) : CachedTypedWritableReferenceCount(copy) {
00046   _node_ref_count = 0;
00047 }
00048 
00049 ////////////////////////////////////////////////////////////////////
00050 //     Function: NodeCachedReferenceCount::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 NodeCachedReferenceCount::
00063 operator = (const NodeCachedReferenceCount &copy) {
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(_node_ref_count != -100);
00074 
00075   CachedTypedWritableReferenceCount::operator = (copy);
00076 }
00077 
00078 ////////////////////////////////////////////////////////////////////
00079 //     Function: NodeCachedReferenceCount::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 NodeCachedReferenceCount::
00090 ~NodeCachedReferenceCount() {
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(_node_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(_node_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(_node_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   _node_ref_count = -100;
00124 #endif
00125 }
00126 
00127 ////////////////////////////////////////////////////////////////////
00128 //     Function: NodeCachedReferenceCount::get_node_ref_count
00129 //       Access: Published
00130 //  Description: Returns the current reference count.
00131 ////////////////////////////////////////////////////////////////////
00132 INLINE int NodeCachedReferenceCount::
00133 get_node_ref_count() const {
00134 #ifdef _DEBUG
00135   test_ref_count_integrity();
00136 #endif
00137   return AtomicAdjust::get(_node_ref_count);
00138 }
00139 
00140 ////////////////////////////////////////////////////////////////////
00141 //     Function: NodeCachedReferenceCount::node_ref
00142 //       Access: Published
00143 //  Description: Explicitly increments the reference count.
00144 //
00145 //               This function is const, even though it changes the
00146 //               object, because generally fiddling with an object's
00147 //               reference count isn't considered part of fiddling
00148 //               with the object.  An object might be const in other
00149 //               ways, but we still need to accurately count the
00150 //               number of references to it.
00151 ////////////////////////////////////////////////////////////////////
00152 INLINE void NodeCachedReferenceCount::
00153 node_ref() const {
00154 #ifdef _DEBUG
00155   nassertv(test_ref_count_integrity());
00156 #endif
00157 
00158   ref();
00159   AtomicAdjust::inc(((NodeCachedReferenceCount *)this)->_node_ref_count);
00160 }
00161 
00162 ////////////////////////////////////////////////////////////////////
00163 //     Function: NodeCachedReferenceCount::node_unref
00164 //       Access: Published
00165 //  Description: Explicitly decrements the node reference count and
00166 //               the normal reference count simultaneously.
00167 //
00168 //               The return value is true if the new reference count
00169 //               is nonzero, false if it is zero.
00170 ////////////////////////////////////////////////////////////////////
00171 INLINE bool NodeCachedReferenceCount::
00172 node_unref() const {
00173   node_unref_only();
00174   return unref();
00175 }
00176 
00177 ////////////////////////////////////////////////////////////////////
00178 //     Function: NodeCachedReferenceCount::test_ref_count_integrity
00179 //       Access: Published
00180 //  Description: Does some easy checks to make sure that the reference
00181 //               count isn't completely bogus.
00182 ////////////////////////////////////////////////////////////////////
00183 INLINE bool NodeCachedReferenceCount::
00184 test_ref_count_integrity() const {
00185 #ifndef NDEBUG
00186   return do_test_ref_count_integrity();
00187 #else
00188   return true;
00189 #endif
00190 }
00191 
00192 ////////////////////////////////////////////////////////////////////
00193 //     Function: NodeCachedReferenceCount::get_referenced_bits
00194 //       Access: Published
00195 //  Description: Returns the union of the values defined in the
00196 //               Referenced enum that represents the various things
00197 //               that appear to be holding a pointer to this object.
00198 //
00199 //               If R_node is included, at least one node is holding a
00200 //               pointer; if R_cache is included, at least one cache
00201 //               element is.
00202 ////////////////////////////////////////////////////////////////////
00203 INLINE int NodeCachedReferenceCount::
00204 get_referenced_bits() const {
00205   int result = 0;
00206   if (get_node_ref_count() != 0) {
00207     result |= R_node;
00208   }
00209   if (get_cache_ref_count() != 0) {
00210     result |= R_cache;
00211   }
00212 
00213   return result;
00214 }
00215 
00216 ////////////////////////////////////////////////////////////////////
00217 //     Function: NodeCachedReferenceCount::node_unref_only
00218 //       Access: Protected
00219 //  Description: Decrements the node reference count without affecting
00220 //               the normal reference count.  Intended to be called by
00221 //               derived classes only, presumably to reimplement
00222 //               node_unref().
00223 ////////////////////////////////////////////////////////////////////
00224 INLINE void NodeCachedReferenceCount::
00225 node_unref_only() const {
00226 #ifdef _DEBUG
00227   nassertv(test_ref_count_integrity());
00228 #endif
00229 
00230   // If this assertion fails, you tried to unref an object with a
00231   // zero reference count.  Are you using ref() and unref()
00232   // directly?  Are you sure you can't use PointerTo's?
00233   nassertv(_node_ref_count > 0);
00234 
00235   AtomicAdjust::dec(((NodeCachedReferenceCount *)this)->_node_ref_count);
00236 }
 All Classes Functions Variables Enumerations