Panda3D
cachedTypedWritableReferenceCount.I
1 // Filename: cachedTypedWritableReferenceCount.I
2 // Created by: drose (25Jan05)
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 ////////////////////////////////////////////////////////////////////
17 // Function: CachedTypedWritableReferenceCount::Constructor
18 // Access: Protected
19 // Description: The ReferenceCount constructor is protected because
20 // you almost never want to create just a ReferenceCount
21 // object by itself, and it's probably a mistake if you
22 // try.
23 //
24 // ReferenceCount doesn't store any useful information
25 // in its own right; its only purpose is to add
26 // reference-counting to some other class via
27 // inheritance.
28 ////////////////////////////////////////////////////////////////////
29 INLINE CachedTypedWritableReferenceCount::
30 CachedTypedWritableReferenceCount() {
31  _cache_ref_count = 0;
32 }
33 
34 ////////////////////////////////////////////////////////////////////
35 // Function: CachedTypedWritableReferenceCount::Copy Constructor
36 // Access: Protected
37 // Description: The copies of reference-counted objects do not
38 // themselves inherit the reference count!
39 //
40 // This copy constructor is protected because you almost
41 // never want to create just a ReferenceCount object by
42 // itself, and it's probably a mistake if you try.
43 ////////////////////////////////////////////////////////////////////
44 INLINE CachedTypedWritableReferenceCount::
45 CachedTypedWritableReferenceCount(const CachedTypedWritableReferenceCount &copy) : TypedWritableReferenceCount(copy) {
46  _cache_ref_count = 0;
47 }
48 
49 ////////////////////////////////////////////////////////////////////
50 // Function: CachedTypedWritableReferenceCount::Copy Assignment Operator
51 // Access: Protected
52 // Description: The copies of reference-counted objects do not
53 // themselves inherit the reference count!
54 //
55 // This copy assignment operator is protected because
56 // you almost never want to copy just a ReferenceCount
57 // object by itself, and it's probably a mistake if you
58 // try. Instead, this should only be called from a
59 // derived class that implements this operator and then
60 // calls up the inheritance chain.
61 ////////////////////////////////////////////////////////////////////
62 INLINE void CachedTypedWritableReferenceCount::
63 operator = (const CachedTypedWritableReferenceCount &copy) {
64  nassertv(this != NULL);
65 
66  // If this assertion fails, our own pointer was recently deleted.
67  // Possibly you used a real pointer instead of a PointerTo at some
68  // point, and the object was deleted when the PointerTo went out of
69  // scope. Maybe you tried to create an automatic (local variable)
70  // instance of a class that derives from ReferenceCount. Or maybe
71  // your headers are out of sync, and you need to make clean in
72  // direct or some higher tree.
73  nassertv(_cache_ref_count != -100);
74 
75  TypedWritableReferenceCount::operator = (copy);
76 }
77 
78 ////////////////////////////////////////////////////////////////////
79 // Function: CachedTypedWritableReferenceCount::Destructor
80 // Access: Protected
81 // Description: The ReferenceCount destructor is protected to
82 // discourage users from accidentally trying to delete a
83 // ReferenceCount pointer directly. This is almost
84 // always a bad idea, since the destructor is not
85 // virtual, and you've almost certainly got some pointer
86 // to something that inherits from ReferenceCount, not
87 // just a plain old ReferenceCount object.
88 ////////////////////////////////////////////////////////////////////
89 INLINE CachedTypedWritableReferenceCount::
90 ~CachedTypedWritableReferenceCount() {
91  nassertv(this != NULL);
92 
93  // If this assertion fails, we're trying to delete an object that
94  // was just deleted. Possibly you used a real pointer instead of a
95  // PointerTo at some point, and the object was deleted when the
96  // PointerTo went out of scope. Maybe you tried to create an
97  // automatic (local variable) instance of a class that derives from
98  // ReferenceCount. Or maybe your headers are out of sync, and you
99  // need to make clean in direct or some higher tree.
100  nassertv(_cache_ref_count != -100);
101 
102  // If this assertion fails, the reference counts are all screwed
103  // up altogether. Maybe some errant code stomped all over memory
104  // somewhere.
105  nassertv(_cache_ref_count >= 0);
106 
107  // If this assertion fails, someone tried to delete this object
108  // while its reference count was still positive. Maybe you tried
109  // to point a PointerTo at a static object (a local variable,
110  // instead of one allocated via new)? The test below against 0x7f
111  // is supposed to check for that, but it's a pretty hokey test.
112 
113  // Another possibility is you inadvertently omitted a copy
114  // constructor for a ReferenceCount object, and then bitwise
115  // copied a dynamically allocated value--reference count and
116  // all--onto a locally allocated one.
117  nassertv(_cache_ref_count == 0);
118 
119 #ifndef NDEBUG
120  // Ok, all clear to delete. Now set the reference count to -100,
121  // so we'll have a better chance of noticing if we happen to have
122  // a stray pointer to it still out there.
123  _cache_ref_count = -100;
124 #endif
125 }
126 
127 ////////////////////////////////////////////////////////////////////
128 // Function: CachedTypedWritableReferenceCount::get_cache_ref_count
129 // Access: Published
130 // Description: Returns the current reference count.
131 ////////////////////////////////////////////////////////////////////
134 #ifdef _DEBUG
136 #endif
137  return AtomicAdjust::get(_cache_ref_count);
138 }
139 
140 ////////////////////////////////////////////////////////////////////
141 // Function: CachedTypedWritableReferenceCount::cache_ref
142 // Access: Published
143 // Description: Explicitly increments the cache reference count and
144 // the normal reference count simultaneously.
145 ////////////////////////////////////////////////////////////////////
147 cache_ref() const {
148 #ifdef _DEBUG
149  nassertv(test_ref_count_integrity());
150 #endif
151 
152  ref();
153  AtomicAdjust::inc(((CachedTypedWritableReferenceCount *)this)->_cache_ref_count);
154 }
155 
156 ////////////////////////////////////////////////////////////////////
157 // Function: CachedTypedWritableReferenceCount::cache_unref
158 // Access: Published
159 // Description: Explicitly decrements the cache reference count and
160 // the normal reference count simultaneously.
161 //
162 // The return value is true if the new reference count
163 // is nonzero, false if it is zero.
164 ////////////////////////////////////////////////////////////////////
166 cache_unref() const {
167 #ifdef _DEBUG
168  nassertr(test_ref_count_integrity(), 0);
169 #endif
170 
171  // If this assertion fails, you tried to unref an object with a
172  // zero reference count. Are you using ref() and unref()
173  // directly? Are you sure you can't use PointerTo's?
174  nassertr(_cache_ref_count > 0, 0);
175 
176  AtomicAdjust::dec(((CachedTypedWritableReferenceCount *)this)->_cache_ref_count);
177  return ReferenceCount::unref();
178 }
179 
180 ////////////////////////////////////////////////////////////////////
181 // Function: CachedTypedWritableReferenceCount::test_ref_count_integrity
182 // Access: Published
183 // Description: Does some easy checks to make sure that the reference
184 // count isn't completely bogus.
185 ////////////////////////////////////////////////////////////////////
188 #ifndef NDEBUG
189  return do_test_ref_count_integrity();
190 #else
191  return true;
192 #endif
193 }
194 
195 ////////////////////////////////////////////////////////////////////
196 // Function: CachedTypedWritableReferenceCount::cache_unref_only
197 // Access: Protected
198 // Description: Decrements the cache reference count without affecting
199 // the normal reference count. Intended to be called by
200 // derived classes only, presumably to reimplement
201 // cache_unref().
202 ////////////////////////////////////////////////////////////////////
203 INLINE void CachedTypedWritableReferenceCount::
204 cache_unref_only() const {
205 #ifdef _DEBUG
206  nassertv(test_ref_count_integrity());
207 #endif
208 
209  // If this assertion fails, you tried to unref an object with a
210  // zero reference count. Are you using ref() and unref()
211  // directly? Are you sure you can't use PointerTo's?
212  nassertv(_cache_ref_count > 0);
213 
214  AtomicAdjust::dec(((CachedTypedWritableReferenceCount *)this)->_cache_ref_count);
215 }
216 
217 ////////////////////////////////////////////////////////////////////
218 // Function: cache_unref_delete
219 // Description: This global helper function will unref the given
220 // ReferenceCount object, and if the reference count
221 // reaches zero, automatically delete it. It can't be a
222 // member function because it's usually a bad idea to
223 // delete an object from within its own member function.
224 // It's a template function so the destructor doesn't
225 // have to be virtual.
226 ////////////////////////////////////////////////////////////////////
227 template<class RefCountType>
228 INLINE void
229 cache_unref_delete(RefCountType *ptr) {
230  if (!ptr->cache_unref()) {
231  delete ptr;
232  }
233 }
234 
bool test_ref_count_integrity() const
Does some easy checks to make sure that the reference count isn&#39;t completely bogus.
This is a special extension to ReferenceCount that includes dual reference counts: the standard refer...
int get_cache_ref_count() const
Returns the current reference count.
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 cache_unref() const
Explicitly decrements the cache reference count and the normal reference count simultaneously.
void cache_ref() const
Explicitly increments the cache reference count and the normal reference count simultaneously.
static Integer get(const Integer &var)
Atomically retrieves the snapshot value of the indicated variable.
A base class for things which need to inherit from both TypedWritable and from ReferenceCount.
void ref() const
Explicitly increments the reference count.
virtual bool unref() const
Explicitly decrements the reference count.