Panda3D

Loading...
Searching...
No Matches
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 */
26INLINE NodeReferenceCount::
27NodeReferenceCount() {
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 */
39INLINE NodeReferenceCount::
40NodeReferenceCount(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 */
53INLINE void NodeReferenceCount::
54operator = (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 */
73INLINE 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 */
109INLINE 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 */
121INLINE 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 */
138INLINE 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 */
148INLINE 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 */
162INLINE 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>
184INLINE 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>
197INLINE NodeRefCountObj<Base>::
198 NodeRefCountObj() {
199}
200
201/**
202 *
203 */
204 template<class Base>
205INLINE 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__) && (!defined(__GNUC__) || defined(__GXX_RTTI))
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