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