Panda3D
nodeCachedReferenceCount.I
1 // Filename: nodeCachedReferenceCount.I
2 // Created by: drose (07May05)
3 //
4 ////////////////////////////////////////////////////////////////////
5 //
6 // PANDA 3D SOFTWARE
7 // Copyright (c) Carnegie Mellon University. All rights reserved.
8 //
9 // All use of this software is subject to the terms of the revised BSD
10 // license. You should have received a copy of this license along
11 // with this source code in a file named "LICENSE."
12 //
13 ////////////////////////////////////////////////////////////////////
14 
15 
16 ////////////////////////////////////////////////////////////////////
17 // Function: NodeCachedReferenceCount::Constructor
18 // Access: Protected
19 // Description: The ReferenceCount constructor is protected because
20 // you almost never want to create just a ReferenceCount
21 // object by itself, and it's probably a mistake if you
22 // try.
23 //
24 // ReferenceCount doesn't store any useful information
25 // in its own right; its only purpose is to add
26 // reference-counting to some other class via
27 // inheritance.
28 ////////////////////////////////////////////////////////////////////
29 INLINE NodeCachedReferenceCount::
30 NodeCachedReferenceCount() {
31  _node_ref_count = 0;
32 }
33 
34 ////////////////////////////////////////////////////////////////////
35 // Function: NodeCachedReferenceCount::Copy Constructor
36 // Access: Protected
37 // Description: The copies of reference-counted objects do not
38 // themselves inherit the reference count!
39 //
40 // This copy constructor is protected because you almost
41 // never want to create just a ReferenceCount object by
42 // itself, and it's probably a mistake if you try.
43 ////////////////////////////////////////////////////////////////////
44 INLINE NodeCachedReferenceCount::
45 NodeCachedReferenceCount(const NodeCachedReferenceCount &copy) : CachedTypedWritableReferenceCount(copy) {
46  _node_ref_count = 0;
47 }
48 
49 ////////////////////////////////////////////////////////////////////
50 // Function: NodeCachedReferenceCount::Copy Assignment Operator
51 // Access: Protected
52 // Description: The copies of reference-counted objects do not
53 // themselves inherit the reference count!
54 //
55 // This copy assignment operator is protected because
56 // you almost never want to copy just a ReferenceCount
57 // object by itself, and it's probably a mistake if you
58 // try. Instead, this should only be called from a
59 // derived class that implements this operator and then
60 // calls up the inheritance chain.
61 ////////////////////////////////////////////////////////////////////
62 INLINE void NodeCachedReferenceCount::
63 operator = (const NodeCachedReferenceCount &copy) {
64  nassertv(this != NULL);
65 
66  // If this assertion fails, our own pointer was recently deleted.
67  // Possibly you used a real pointer instead of a PointerTo at some
68  // point, and the object was deleted when the PointerTo went out of
69  // scope. Maybe you tried to create an automatic (local variable)
70  // instance of a class that derives from ReferenceCount. Or maybe
71  // your headers are out of sync, and you need to make clean in
72  // direct or some higher tree.
73  nassertv(_node_ref_count != -100);
74 
75  CachedTypedWritableReferenceCount::operator = (copy);
76 }
77 
78 ////////////////////////////////////////////////////////////////////
79 // Function: NodeCachedReferenceCount::Destructor
80 // Access: Protected
81 // Description: The ReferenceCount destructor is protected to
82 // discourage users from accidentally trying to delete a
83 // ReferenceCount pointer directly. This is almost
84 // always a bad idea, since the destructor is not
85 // virtual, and you've almost certainly got some pointer
86 // to something that inherits from ReferenceCount, not
87 // just a plain old ReferenceCount object.
88 ////////////////////////////////////////////////////////////////////
89 INLINE NodeCachedReferenceCount::
90 ~NodeCachedReferenceCount() {
91  nassertv(this != NULL);
92 
93  // If this assertion fails, we're trying to delete an object that
94  // was just deleted. Possibly you used a real pointer instead of a
95  // PointerTo at some point, and the object was deleted when the
96  // PointerTo went out of scope. Maybe you tried to create an
97  // automatic (local variable) instance of a class that derives from
98  // ReferenceCount. Or maybe your headers are out of sync, and you
99  // need to make clean in direct or some higher tree.
100  nassertv(_node_ref_count != -100);
101 
102  // If this assertion fails, the reference counts are all screwed
103  // up altogether. Maybe some errant code stomped all over memory
104  // somewhere.
105  nassertv(_node_ref_count >= 0);
106 
107  // If this assertion fails, someone tried to delete this object
108  // while its reference count was still positive. Maybe you tried
109  // to point a PointerTo at a static object (a local variable,
110  // instead of one allocated via new)? The test below against 0x7f
111  // is supposed to check for that, but it's a pretty hokey test.
112 
113  // Another possibility is you inadvertently omitted a copy
114  // constructor for a ReferenceCount object, and then bitwise
115  // copied a dynamically allocated value--reference count and
116  // all--onto a locally allocated one.
117  nassertv(_node_ref_count == 0);
118 
119 #ifndef NDEBUG
120  // Ok, all clear to delete. Now set the reference count to -100,
121  // so we'll have a better chance of noticing if we happen to have
122  // a stray pointer to it still out there.
123  _node_ref_count = -100;
124 #endif
125 }
126 
127 ////////////////////////////////////////////////////////////////////
128 // Function: NodeCachedReferenceCount::get_node_ref_count
129 // Access: Published
130 // Description: Returns the current reference count.
131 ////////////////////////////////////////////////////////////////////
134 #ifdef _DEBUG
136 #endif
137  return AtomicAdjust::get(_node_ref_count);
138 }
139 
140 ////////////////////////////////////////////////////////////////////
141 // Function: NodeCachedReferenceCount::node_ref
142 // Access: Published
143 // Description: Explicitly increments the reference count.
144 //
145 // This function is const, even though it changes the
146 // object, because generally fiddling with an object's
147 // reference count isn't considered part of fiddling
148 // with the object. An object might be const in other
149 // ways, but we still need to accurately count the
150 // number of references to it.
151 ////////////////////////////////////////////////////////////////////
152 INLINE void NodeCachedReferenceCount::
153 node_ref() const {
154 #ifdef _DEBUG
155  nassertv(test_ref_count_integrity());
156 #endif
157 
158  ref();
159  AtomicAdjust::inc(((NodeCachedReferenceCount *)this)->_node_ref_count);
160 }
161 
162 ////////////////////////////////////////////////////////////////////
163 // Function: NodeCachedReferenceCount::node_unref
164 // Access: Published
165 // Description: Explicitly decrements the node reference count and
166 // the normal reference count simultaneously.
167 //
168 // The return value is true if the new reference count
169 // is nonzero, false if it is zero.
170 ////////////////////////////////////////////////////////////////////
171 INLINE bool NodeCachedReferenceCount::
172 node_unref() const {
173  node_unref_only();
174  return unref();
175 }
176 
177 ////////////////////////////////////////////////////////////////////
178 // Function: NodeCachedReferenceCount::test_ref_count_integrity
179 // Access: Published
180 // Description: Does some easy checks to make sure that the reference
181 // count isn't completely bogus.
182 ////////////////////////////////////////////////////////////////////
183 INLINE bool NodeCachedReferenceCount::
185 #ifndef NDEBUG
186  return do_test_ref_count_integrity();
187 #else
188  return true;
189 #endif
190 }
191 
192 ////////////////////////////////////////////////////////////////////
193 // Function: NodeCachedReferenceCount::get_referenced_bits
194 // Access: Published
195 // Description: Returns the union of the values defined in the
196 // Referenced enum that represents the various things
197 // that appear to be holding a pointer to this object.
198 //
199 // If R_node is included, at least one node is holding a
200 // pointer; if R_cache is included, at least one cache
201 // element is.
202 ////////////////////////////////////////////////////////////////////
205  int result = 0;
206  if (get_node_ref_count() != 0) {
207  result |= R_node;
208  }
209  if (get_cache_ref_count() != 0) {
210  result |= R_cache;
211  }
212 
213  return result;
214 }
215 
216 ////////////////////////////////////////////////////////////////////
217 // Function: NodeCachedReferenceCount::node_unref_only
218 // Access: Protected
219 // Description: Decrements the node reference count without affecting
220 // the normal reference count. Intended to be called by
221 // derived classes only, presumably to reimplement
222 // node_unref().
223 ////////////////////////////////////////////////////////////////////
224 INLINE void NodeCachedReferenceCount::
225 node_unref_only() const {
226 #ifdef _DEBUG
227  nassertv(test_ref_count_integrity());
228 #endif
229 
230  // If this assertion fails, you tried to unref an object with a
231  // zero reference count. Are you using ref() and unref()
232  // directly? Are you sure you can't use PointerTo's?
233  nassertv(_node_ref_count > 0);
234 
235  AtomicAdjust::dec(((NodeCachedReferenceCount *)this)->_node_ref_count);
236 }
This class further specializes CachedTypedWritableReferenceCount to also add a node_ref_count, for the purposes of counting the number of times the object is referenced by a "node", presumably a PandaNode.
This is a special extension to ReferenceCount that includes dual reference counts: the standard refer...
bool test_ref_count_integrity() const
Does some easy checks to make sure that the reference count isn't completely bogus.
void node_ref() const
Explicitly increments the reference count.
int get_cache_ref_count() const
Returns the current reference count.
static void inc(Integer &var)
Atomically increments the indicated variable.
static bool dec(Integer &var)
Atomically decrements the indicated variable and returns true if the new value is nonzero...
static Integer get(const Integer &var)
Atomically retrieves the snapshot value of the indicated variable.
bool node_unref() const
Explicitly decrements the node reference count and the normal reference count simultaneously.
void ref() const
Explicitly increments the reference count.
int get_node_ref_count() const
Returns the current reference count.
int get_referenced_bits() const
Returns the union of the values defined in the Referenced enum that represents the various things tha...
virtual bool unref() const
Explicitly decrements the reference count.