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
14template<class Base>
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 */
110get_node_ref_count() const {
111#ifdef _DEBUG
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 */
122node_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 */
139node_unref() const {
141 return unref();
142}
143
144/**
145 * Does some easy checks to make sure that the reference count isn't
146 * completely bogus.
147 */
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 */
163node_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 */
183template<class RefCountType>
184INLINE void
185node_unref_delete(RefCountType *ptr) {
186 if (!ptr->node_unref()) {
187 delete ptr;
188 }
189}
190
191
192
193/**
194 *
195 */
196template<class Base>
199}
200
201/**
202 *
203 */
204template<class Base>
206NodeRefCountObj(const Base &copy) : Base(copy) {
207}
208
209
210/**
211 *
212 */
213template<class Base>
215init_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}
static bool dec(Integer &var)
Atomically decrements the indicated variable and returns true if the new value is nonzero,...
static void inc(Integer &var)
Atomically increments the indicated variable.
static Integer get(const Integer &var)
Atomically retrieves the snapshot value of the indicated variable.
This works like RefCountObj, but it inherits from NodeReferenceCount instead of ReferenceCount.
This class specializes ReferenceCount to add an additional counter, called node_ref_count,...
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't completely bogus.
bool node_unref() const
Explicitly decrements the node reference count and the normal reference count simultaneously.
int get_node_ref_count() const
Returns the current reference count.
void node_unref_only() const
Decrements the node reference count without affecting the normal reference count.
A base class for all things that want to be reference-counted.
void ref() const
Explicitly increments the reference count.
virtual bool unref() const
Explicitly decrements the reference count.
TypeHandle is the identifier used to differentiate C++ class types.
Definition typeHandle.h:81
void node_unref_delete(RefCountType *ptr)
This global helper function will unref the given ReferenceCount object, and if the reference count re...
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...