Panda3D

copyOnWritePointer.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 copyOnWritePointer.I
10 * @author drose
11 * @date 2007-04-09
12 */
13
14 /**
15 *
16 */
17 INLINE CopyOnWritePointer::
18 CopyOnWritePointer(CopyOnWriteObject *object) :
19 _cow_object(object)
20 {
21 if (_cow_object != nullptr) {
22 _cow_object->cache_ref();
23 }
24 }
25
26 /**
27 *
28 */
29 INLINE CopyOnWritePointer::
30 CopyOnWritePointer(const CopyOnWritePointer &copy) :
31 _cow_object(copy._cow_object)
32 {
33 if (_cow_object != nullptr) {
34 _cow_object->cache_ref();
35 }
36 }
37
38 /**
39 *
40 */
41 INLINE void CopyOnWritePointer::
42 operator = (const CopyOnWritePointer &copy) {
43 operator = (copy._cow_object);
44 }
45
46 /**
47 *
48 */
49 INLINE void CopyOnWritePointer::
50 operator = (CopyOnWriteObject *object) {
51 if (_cow_object != object) {
52 if (_cow_object != nullptr) {
53 cache_unref_delete(_cow_object);
54 }
55 _cow_object = object;
56 if (_cow_object != nullptr) {
57 _cow_object->cache_ref();
58 }
59 }
60 }
61
62 /**
63 *
64 */
65 INLINE CopyOnWritePointer::
66 ~CopyOnWritePointer() {
67 if (_cow_object != nullptr) {
68 cache_unref_delete(_cow_object);
69 }
70 }
71
72 /**
73 *
74 */
75 INLINE CopyOnWritePointer::
76 CopyOnWritePointer(CopyOnWritePointer &&from) noexcept :
77 _cow_object(from._cow_object)
78 {
79 // Steal the other's reference count.
80 from._cow_object = nullptr;
81 }
82
83 /**
84 *
85 */
86 INLINE CopyOnWritePointer::
87 CopyOnWritePointer(PointerTo<CopyOnWriteObject> &&from) noexcept :
88 _cow_object(from.p())
89 {
90 // Steal the other's reference count, but because it is a regular pointer,
91 // we do need to include the cache reference count.
92 if (_cow_object != nullptr) {
93 _cow_object->cache_ref_only();
94 }
95 from.cheat() = nullptr;
96 }
97
98 /**
99 *
100 */
101 INLINE void CopyOnWritePointer::
102 operator = (CopyOnWritePointer &&from) noexcept {
103 // Protect against self-move-assignment.
104 if (from._cow_object != _cow_object) {
105 CopyOnWriteObject *old_object = _cow_object;
106 _cow_object = from._cow_object;
107 from._cow_object = nullptr;
108
109 if (old_object != nullptr) {
110 cache_unref_delete(old_object);
111 }
112 }
113 }
114
115 /**
116 *
117 */
118 INLINE void CopyOnWritePointer::
119 operator = (PointerTo<CopyOnWriteObject> &&from) noexcept {
120 if (from.p() != _cow_object) {
121 CopyOnWriteObject *old_object = _cow_object;
122
123 // Steal the other's reference count, but because it is a regular pointer,
124 // we do need to include the cache reference count.
125 _cow_object = from.p();
126 _cow_object->cache_ref_only();
127 from.cheat() = nullptr;
128
129 if (old_object != nullptr) {
130 cache_unref_delete(old_object);
131 }
132 }
133 }
134
135 /**
136 *
137 */
138 INLINE bool CopyOnWritePointer::
139 operator == (const CopyOnWritePointer &other) const {
140 return _cow_object == other._cow_object;
141 }
142
143 /**
144 *
145 */
146 INLINE bool CopyOnWritePointer::
147 operator != (const CopyOnWritePointer &other) const {
148 return _cow_object != other._cow_object;
149 }
150
151 /**
152 *
153 */
154 INLINE bool CopyOnWritePointer::
155 operator < (const CopyOnWritePointer &other) const {
156 return _cow_object < other._cow_object;
157 }
158
159 #ifndef COW_THREADED
160 /**
161 * Returns a pointer locked for read. Until this pointer dereferences, calls
162 * to get_write_pointer() will force a copy.
163 *
164 * This flavor of the method is written for the non-threaded case.
165 */
166 INLINE const CopyOnWriteObject *CopyOnWritePointer::
167 get_read_pointer(Thread *current_thread) const {
168 return _cow_object;
169 }
170 #endif // COW_THREADED
171
172 #ifndef COW_THREADED
173 /**
174 * Returns a pointer locked for write. If another thread or threads already
175 * hold the pointer locked for read, then this will force a copy.
176 *
177 * Until this pointer dereferences, calls to get_read_pointer() or
178 * get_write_pointer() will block.
179 *
180 * This flavor of the method is written for the non-threaded case.
181 */
182 INLINE CopyOnWriteObject *CopyOnWritePointer::
183 get_write_pointer() {
184 if (_cow_object == nullptr) {
185 return nullptr;
186 }
187 if (_cow_object->get_cache_ref_count() > 1) {
188 PT(CopyOnWriteObject) new_object = _cow_object->make_cow_copy();
189 cache_unref_delete(_cow_object);
190 _cow_object = new_object;
191 _cow_object->cache_ref();
192 }
193 return _cow_object;
194 }
195 #endif // COW_THREADED
196
197 /**
198 * Returns an unlocked pointer that you can write to. This should only be
199 * used in very narrow circumstances in which you know that no other thread
200 * may be accessing the pointer at the same time.
201 */
202 INLINE CopyOnWriteObject *CopyOnWritePointer::
203 get_unsafe_pointer() {
204 return _cow_object;
205 }
206
207 /**
208 * Returns true if the CopyOnWritePointer contains a NULL pointer, false
209 * otherwise.
210 */
211 bool CopyOnWritePointer::
212 is_null() const {
213 return (_cow_object == nullptr);
214 }
215
216 /**
217 * Sets the pointer to NULL.
218 */
219 void CopyOnWritePointer::
220 clear() {
221 if (_cow_object != nullptr) {
222 cache_unref_delete(_cow_object);
223 }
224 _cow_object = nullptr;
225 }
226
227 /**
228 * Does some easy checks to make sure that the reference count isn't
229 * completely bogus. Returns true if ok, false otherwise.
230 */
231 INLINE bool CopyOnWritePointer::
232 test_ref_count_integrity() const {
233 nassertr(_cow_object != nullptr, false);
234 return _cow_object->test_ref_count_integrity();
235 }
236
237 /**
238 * Does some easy checks to make sure that the reference count isn't zero, or
239 * completely bogus. Returns true if ok, false otherwise.
240 */
241 INLINE bool CopyOnWritePointer::
242 test_ref_count_nonzero() const {
243 nassertr(_cow_object != nullptr, false);
244 return _cow_object->test_ref_count_nonzero();
245 }
246
247 #ifndef CPPPARSER
248 /**
249 *
250 */
251 template<class T>
252 INLINE CopyOnWritePointerTo<T>::
253 CopyOnWritePointerTo(To *object) : CopyOnWritePointer(object) {
254 }
255 #endif // CPPPARSER
256
257 #ifndef CPPPARSER
258 /**
259 *
260 */
261 template<class T>
262 INLINE CopyOnWritePointerTo<T>::
263 CopyOnWritePointerTo(const CopyOnWritePointerTo<T> &copy) :
264 CopyOnWritePointer(copy)
265 {
266 }
267 #endif // CPPPARSER
268
269 #ifndef CPPPARSER
270 /**
271 *
272 */
273 template<class T>
274 INLINE void CopyOnWritePointerTo<T>::
275 operator = (const CopyOnWritePointerTo<T> &copy) {
276 CopyOnWritePointer::operator = (copy);
277 }
278 #endif // CPPPARSER
279
280 #ifndef CPPPARSER
281 /**
282 *
283 */
284 template<class T>
285 INLINE void CopyOnWritePointerTo<T>::
286 operator = (To *object) {
287 CopyOnWritePointer::operator = (object);
288 }
289 #endif // CPPPARSER
290
291 #ifndef CPPPARSER
292 /**
293 *
294 */
295 template<class T>
296 INLINE CopyOnWritePointerTo<T>::
297 CopyOnWritePointerTo(CopyOnWritePointerTo<T> &&from) noexcept :
298 CopyOnWritePointer((CopyOnWritePointer &&)from)
299 {
300 }
301 #endif // CPPPARSER
302
303 #ifndef CPPPARSER
304 /**
305 *
306 */
307 template<class T>
308 INLINE CopyOnWritePointerTo<T>::
309 CopyOnWritePointerTo(PointerTo<T> &&from) noexcept {
310 // Steal the other's reference count, but because it is a regular pointer,
311 // we do need to include the cache reference count.
312 _cow_object = from.p();
313 if (_cow_object != nullptr) {
314 _cow_object->cache_ref_only();
315 }
316 from.cheat() = nullptr;
317 }
318 #endif // CPPPARSER
319
320 #ifndef CPPPARSER
321 /**
322 *
323 */
324 template<class T>
325 INLINE void CopyOnWritePointerTo<T>::
326 operator = (CopyOnWritePointerTo<T> &&from) noexcept {
327 CopyOnWritePointer::operator = ((CopyOnWritePointer &&)from);
328 }
329 #endif // CPPPARSER
330
331 #ifndef CPPPARSER
332 /**
333 *
334 */
335 template<class T>
336 INLINE void CopyOnWritePointerTo<T>::
337 operator = (PointerTo<T> &&from) noexcept {
338 if (from.p() != _cow_object) {
339 CopyOnWriteObject *old_object = _cow_object;
340
341 // Steal the other's reference count, but because it is a regular pointer,
342 // we do need to include the cache reference count.
343 _cow_object = from.p();
344 _cow_object->cache_ref_only();
345 from.cheat() = nullptr;
346
347 if (old_object != nullptr) {
348 cache_unref_delete(old_object);
349 }
350 }
351 }
352 #endif // CPPPARSER
353
354 #ifndef CPPPARSER
355 #ifdef COW_THREADED
356 /**
357 * See CopyOnWritePointer::get_read_pointer().
358 */
359 template<class T>
360 INLINE CPT(typename CopyOnWritePointerTo<T>::To) CopyOnWritePointerTo<T>::
361 get_read_pointer(Thread *current_thread) const {
362 // This is necessary because we don't currently have a way to cast between
363 // two compatible PointerTo types without losing the reference count.
364 CPT(typename CopyOnWritePointerTo<T>::To) to;
365 CPT(CopyOnWriteObject) from = CopyOnWritePointer::get_read_pointer(current_thread);
366 to.cheat() = (const To *)from.p();
367 from.cheat() = nullptr;
368 return to;
369 }
370 #else // COW_THREADED
371 /**
372 * See CopyOnWritePointer::get_read_pointer().
373 */
374 template<class T>
375 INLINE const typename CopyOnWritePointerTo<T>::To *CopyOnWritePointerTo<T>::
376 get_read_pointer(Thread *current_thread) const {
377 return (const To *)CopyOnWritePointer::get_read_pointer(current_thread);
378 }
379 #endif // COW_THREADED
380 #endif // CPPPARSER
381
382 #ifndef CPPPARSER
383 #ifdef COW_THREADED
384 /**
385 * See CopyOnWritePointer::get_write_pointer().
386 */
387 template<class T>
388 INLINE PT(typename CopyOnWritePointerTo<T>::To) CopyOnWritePointerTo<T>::
389 get_write_pointer() {
390 // This is necessary because we don't currently have a way to cast between
391 // two compatible PointerTo types without losing the reference count.
392 PT(typename CopyOnWritePointerTo<T>::To) to;
393 PT(CopyOnWriteObject) from = CopyOnWritePointer::get_write_pointer();
394 to.cheat() = (To *)from.p();
395 from.cheat() = nullptr;
396 return to;
397 }
398 #else // COW_THREADED
399 /**
400 * See CopyOnWritePointer::get_write_pointer().
401 */
402 template<class T>
403 INLINE typename CopyOnWritePointerTo<T>::To *CopyOnWritePointerTo<T>::
404 get_write_pointer() {
405 return (To *)CopyOnWritePointer::get_write_pointer();
406 }
407 #endif // COW_THREADED
408 #endif // CPPPARSER
409
410 #ifndef CPPPARSER
411 /**
412 * See CopyOnWritePointer::get_unsafe_pointer().
413 */
414 template<class T>
415 INLINE typename CopyOnWritePointerTo<T>::To *CopyOnWritePointerTo<T>::
416 get_unsafe_pointer() {
417 return (To *)(CopyOnWritePointer::get_unsafe_pointer());
418 }
419 #endif // CPPPARSER
cache_unref_delete
void cache_unref_delete(RefCountType *ptr)
This global helper function will unref the given ReferenceCount object, and if the reference count re...
Definition: cachedTypedWritableReferenceCount.I:204
CachedTypedWritableReferenceCount::cache_ref
void cache_ref() const
Explicitly increments the cache reference count and the normal reference count simultaneously.
Definition: cachedTypedWritableReferenceCount.I:119
CachedTypedWritableReferenceCount::get_cache_ref_count
get_cache_ref_count
Returns the current reference count.
Definition: cachedTypedWritableReferenceCount.h:47
CachedTypedWritableReferenceCount::cache_ref_only
void cache_ref_only() const
Decrements the cache reference count without affecting the normal reference count.
Definition: cachedTypedWritableReferenceCount.I:168
CachedTypedWritableReferenceCount::test_ref_count_integrity
bool test_ref_count_integrity() const
Does some easy checks to make sure that the reference count isn't completely bogus.
Definition: cachedTypedWritableReferenceCount.I:155
CopyOnWriteObject
This base class provides basic reference counting, but also can be used with a CopyOnWritePointer to ...
Definition: copyOnWriteObject.h:41
CopyOnWritePointerTo
A template wrapper around the above class, mainly to handle the little typecasting niceties.
Definition: copyOnWritePointer.h:74
CopyOnWritePointerTo::get_unsafe_pointer
To * get_unsafe_pointer()
See CopyOnWritePointer::get_unsafe_pointer().
Definition: copyOnWritePointer.I:416
CopyOnWritePointerTo::get_write_pointer
To * get_write_pointer()
See CopyOnWritePointer::get_write_pointer().
Definition: copyOnWritePointer.I:404
CopyOnWritePointerTo::get_read_pointer
const To * get_read_pointer(Thread *current_thread=Thread::get_current_thread()) const
See CopyOnWritePointer::get_read_pointer().
Definition: copyOnWritePointer.I:376
CopyOnWritePointer
This safely stores the primary, owned pointer to a CopyOnWriteObject.
Definition: copyOnWritePointer.h:31
CopyOnWritePointer::is_null
bool is_null() const
Returns true if the CopyOnWritePointer contains a NULL pointer, false otherwise.
Definition: copyOnWritePointer.I:212
CopyOnWritePointer::get_read_pointer
const CopyOnWriteObject * get_read_pointer(Thread *current_thread) const
Returns a pointer locked for read.
Definition: copyOnWritePointer.I:167
CopyOnWritePointer::test_ref_count_integrity
bool test_ref_count_integrity() const
Does some easy checks to make sure that the reference count isn't completely bogus.
Definition: copyOnWritePointer.I:232
CopyOnWritePointer::get_unsafe_pointer
CopyOnWriteObject * get_unsafe_pointer()
Returns an unlocked pointer that you can write to.
Definition: copyOnWritePointer.I:203
CopyOnWritePointer::test_ref_count_nonzero
bool test_ref_count_nonzero() const
Does some easy checks to make sure that the reference count isn't zero, or completely bogus.
Definition: copyOnWritePointer.I:242
CopyOnWritePointer::get_write_pointer
CopyOnWriteObject * get_write_pointer()
Returns a pointer locked for write.
Definition: copyOnWritePointer.I:183
CopyOnWritePointer::clear
void clear()
Sets the pointer to NULL.
Definition: copyOnWritePointer.I:220
PointerTo
This file defines the classes PointerTo and ConstPointerTo (and their abbreviations,...
Definition: pointerTo.h:69
ReferenceCount::test_ref_count_nonzero
bool test_ref_count_nonzero() const
Does some easy checks to make sure that the reference count isn't zero, or completely bogus.
Definition: referenceCount.I:210
Thread
A thread; that is, a lightweight process.
Definition: thread.h:46