Panda3D
 All Classes Functions Variables Enumerations
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...
virtual bool unref() const
Explicitly decrements the reference count.
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.
bool cache_unref() const
Explicitly decrements the cache reference count and the normal reference count simultaneously.