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