Panda3D
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>
17 TypeHandle NodeRefCountObj<Base>::_type_handle;
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 }
bool node_unref() const
Explicitly decrements the node reference count and the normal reference count simultaneously.
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...
bool test_ref_count_integrity() const
Does some easy checks to make sure that the reference count isn&#39;t completely bogus.
int get_node_ref_count() const
Returns the current reference count.
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 "node", whatever that may mean in context.
This works like RefCountObj, but it inherits from NodeReferenceCount instead of ReferenceCount.
void node_ref() const
Explicitly increments the node reference count and the normal reference count simultaneously.
static Integer get(const Integer &var)
Atomically retrieves the snapshot value of the indicated variable.
void ref() const
Explicitly increments the reference count.
A base class for all things that want to be reference-counted.
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:85
virtual bool unref() const
Explicitly decrements the reference count.