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&#39;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...
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.
A base class for things which need to inherit from both TypedWritable and from ReferenceCount.
void ref() const
Explicitly increments the reference count.
static ALWAYS_INLINE Integer get(const Integer &var)
Atomically retrieves the snapshot value of the indicated variable.
static ALWAYS_INLINE void inc(Integer &var)
Atomically increments the indicated variable.
static ALWAYS_INLINE 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.