Panda3D
 All Classes Functions Variables Enumerations
nodeReferenceCount.I
1 // Filename: nodeReferenceCount.I
2 // Created by: drose (01May06)
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 template<class Base>
18 
19 ////////////////////////////////////////////////////////////////////
20 // Function: NodeReferenceCount::Constructor
21 // Access: Protected
22 // Description: The ReferenceCount constructor is protected because
23 // you almost never want to create just a ReferenceCount
24 // object by itself, and it's probably a mistake if you
25 // try.
26 //
27 // ReferenceCount doesn't store any useful information
28 // in its own right; its only purpose is to add
29 // reference-counting to some other class via
30 // inheritance.
31 ////////////////////////////////////////////////////////////////////
32 INLINE NodeReferenceCount::
33 NodeReferenceCount() {
34  _node_ref_count = 0;
35 }
36 
37 ////////////////////////////////////////////////////////////////////
38 // Function: NodeReferenceCount::Copy Constructor
39 // Access: Protected
40 // Description: The copies of reference-counted objects do not
41 // themselves inherit the reference count!
42 //
43 // This copy constructor is protected because you almost
44 // never want to create just a ReferenceCount object by
45 // itself, and it's probably a mistake if you try.
46 ////////////////////////////////////////////////////////////////////
47 INLINE NodeReferenceCount::
48 NodeReferenceCount(const NodeReferenceCount &copy) : ReferenceCount(copy) {
49  _node_ref_count = 0;
50 }
51 
52 ////////////////////////////////////////////////////////////////////
53 // Function: NodeReferenceCount::Copy Assignment Operator
54 // Access: Protected
55 // Description: The copies of reference-counted objects do not
56 // themselves inherit the reference count!
57 //
58 // This copy assignment operator is protected because
59 // you almost never want to copy just a ReferenceCount
60 // object by itself, and it's probably a mistake if you
61 // try. Instead, this should only be called from a
62 // derived class that implements this operator and then
63 // calls up the inheritance chain.
64 ////////////////////////////////////////////////////////////////////
65 INLINE void NodeReferenceCount::
66 operator = (const NodeReferenceCount &copy) {
67  nassertv(this != NULL);
68 
69  // If this assertion fails, our own pointer was recently deleted.
70  // Possibly you used a real pointer instead of a PointerTo at some
71  // point, and the object was deleted when the PointerTo went out of
72  // scope. Maybe you tried to create an automatic (local variable)
73  // instance of a class that derives from ReferenceCount. Or maybe
74  // your headers are out of sync, and you need to make clean in
75  // direct or some higher tree.
76  nassertv(_node_ref_count != -100);
77 
78  ReferenceCount::operator = (copy);
79 }
80 
81 ////////////////////////////////////////////////////////////////////
82 // Function: NodeReferenceCount::Destructor
83 // Access: Protected
84 // Description: The ReferenceCount destructor is protected to
85 // discourage users from accidentally trying to delete a
86 // ReferenceCount pointer directly. This is almost
87 // always a bad idea, since the destructor is not
88 // virtual, and you've almost certainly got some pointer
89 // to something that inherits from ReferenceCount, not
90 // just a plain old ReferenceCount object.
91 ////////////////////////////////////////////////////////////////////
92 INLINE NodeReferenceCount::
93 ~NodeReferenceCount() {
94  nassertv(this != NULL);
95 
96  // If this assertion fails, we're trying to delete an object that
97  // was just deleted. Possibly you used a real pointer instead of a
98  // PointerTo at some point, and the object was deleted when the
99  // PointerTo went out of scope. Maybe you tried to create an
100  // automatic (local variable) instance of a class that derives from
101  // ReferenceCount. Or maybe your headers are out of sync, and you
102  // need to make clean in direct or some higher tree.
103  nassertv(_node_ref_count != -100);
104 
105  // If this assertion fails, the reference counts are all screwed
106  // up altogether. Maybe some errant code stomped all over memory
107  // somewhere.
108  nassertv(_node_ref_count >= 0);
109 
110  // If this assertion fails, someone tried to delete this object
111  // while its reference count was still positive. Maybe you tried
112  // to point a PointerTo at a static object (a local variable,
113  // instead of one allocated via new)? The test below against 0x7f
114  // is supposed to check for that, but it's a pretty hokey test.
115 
116  // Another possibility is you inadvertently omitted a copy
117  // constructor for a ReferenceCount object, and then bitwise
118  // copied a dynamically allocated value--reference count and
119  // all--onto a locally allocated one.
120  nassertv(_node_ref_count == 0);
121 
122 #ifndef NDEBUG
123  // Ok, all clear to delete. Now set the reference count to -100,
124  // so we'll have a better chance of noticing if we happen to have
125  // a stray pointer to it still out there.
126  _node_ref_count = -100;
127 #endif
128 }
129 
130 ////////////////////////////////////////////////////////////////////
131 // Function: NodeReferenceCount::get_node_ref_count
132 // Access: Published
133 // Description: Returns the current reference count.
134 ////////////////////////////////////////////////////////////////////
135 INLINE int NodeReferenceCount::
137 #ifdef _DEBUG
139 #endif
140  return AtomicAdjust::get(_node_ref_count);
141 }
142 
143 ////////////////////////////////////////////////////////////////////
144 // Function: NodeReferenceCount::node_ref
145 // Access: Published
146 // Description: Explicitly increments the node reference count and
147 // the normal reference count simultaneously.
148 ////////////////////////////////////////////////////////////////////
149 INLINE void NodeReferenceCount::
150 node_ref() const {
151 #ifdef _DEBUG
152  nassertv(test_ref_count_integrity());
153 #endif
154 
155  ref();
156  AtomicAdjust::inc(((NodeReferenceCount *)this)->_node_ref_count);
157 }
158 
159 ////////////////////////////////////////////////////////////////////
160 // Function: NodeReferenceCount::node_unref
161 // Access: Published
162 // Description: Explicitly decrements the node reference count and
163 // the normal reference count simultaneously.
164 //
165 // The return value is true if the new reference count
166 // is nonzero, false if it is zero.
167 ////////////////////////////////////////////////////////////////////
168 INLINE bool NodeReferenceCount::
169 node_unref() const {
170  node_unref_only();
171  return unref();
172 }
173 
174 ////////////////////////////////////////////////////////////////////
175 // Function: NodeReferenceCount::test_ref_count_integrity
176 // Access: Published
177 // Description: Does some easy checks to make sure that the reference
178 // count isn't completely bogus.
179 ////////////////////////////////////////////////////////////////////
180 INLINE bool NodeReferenceCount::
182 #ifndef NDEBUG
183  return do_test_ref_count_integrity();
184 #else
185  return true;
186 #endif
187 }
188 
189 ////////////////////////////////////////////////////////////////////
190 // Function: NodeReferenceCount::node_unref_only
191 // Access: Protected
192 // Description: Decrements the node reference count without affecting
193 // the normal reference count. Intended to be called by
194 // derived classes only, presumably to reimplement
195 // node_unref().
196 ////////////////////////////////////////////////////////////////////
197 INLINE void NodeReferenceCount::
198 node_unref_only() const {
199 #ifdef _DEBUG
200  nassertv(test_ref_count_integrity());
201 #endif
202 
203  // If this assertion fails, you tried to unref an object with a
204  // zero reference count. Are you using ref() and unref()
205  // directly? Are you sure you can't use PointerTo's?
206  nassertv(_node_ref_count > 0);
207 
208  AtomicAdjust::dec(((NodeReferenceCount *)this)->_node_ref_count);
209 }
210 
211 ////////////////////////////////////////////////////////////////////
212 // Function: node_unref_delete
213 // Description: This global helper function will unref the given
214 // ReferenceCount object, and if the reference count
215 // reaches zero, automatically delete it. It can't be a
216 // member function because it's usually a bad idea to
217 // delete an object from within its own member function.
218 // It's a template function so the destructor doesn't
219 // have to be virtual.
220 ////////////////////////////////////////////////////////////////////
221 template<class RefCountType>
222 INLINE void
223 node_unref_delete(RefCountType *ptr) {
224  if (!ptr->node_unref()) {
225  delete ptr;
226  }
227 }
228 
229 
230 
231 ////////////////////////////////////////////////////////////////////
232 // Function: NodeRefCountObj::Constructor
233 // Access: Public
234 // Description:
235 ////////////////////////////////////////////////////////////////////
236 template<class Base>
238 NodeRefCountObj() {
239 }
240 
241 ////////////////////////////////////////////////////////////////////
242 // Function: NodeRefCountObj::Copy Constructor
243 // Access: Public
244 // Description:
245 ////////////////////////////////////////////////////////////////////
246 template<class Base>
248 NodeRefCountObj(const Base &copy) : Base(copy) {
249 }
250 
251 
252 ////////////////////////////////////////////////////////////////////
253 // Function: NodeRefCountObj::init_type
254 // Access: Public
255 // Description:
256 ////////////////////////////////////////////////////////////////////
257 template<class Base>
259 init_type() {
260 #if defined(HAVE_RTTI) && !defined(__EDG__)
261  // If we have RTTI, we can determine the name of the base type.
262  string base_name = typeid(Base).name();
263 #else
264  string base_name = "unknown";
265 #endif
266 
267  TypeHandle base_type = register_dynamic_type(base_name);
268 
269  ReferenceCount::init_type();
270  _type_handle =
271  register_dynamic_type("NodeRefCountObj<" + base_name + ">",
272  base_type, ReferenceCount::get_class_type());
273 }
int get_node_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...
This class specializes ReferenceCount to add an additional counter, called node_ref_count, for the purposes of counting the number of times the object is referenced by a &quot;node&quot;, whatever that may mean in context.
This works like RefCountObj, but it inherits from NodeReferenceCount instead of ReferenceCount.
virtual bool unref() const
Explicitly decrements the reference count.
static Integer get(const Integer &var)
Atomically retrieves the snapshot value of the indicated variable.
void node_ref() const
Explicitly increments the node reference count and the normal reference count simultaneously.
bool test_ref_count_integrity() const
Does some easy checks to make sure that the reference count isn&#39;t completely bogus.
A base class for all things that want to be reference-counted.
void ref() const
Explicitly increments the reference count.
bool node_unref() const
Explicitly decrements the node reference count and the normal reference count simultaneously.
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:85