Panda3D

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