Panda3D
Loading...
Searching...
No Matches
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 */
17INLINE CopyOnWritePointer::
18CopyOnWritePointer(CopyOnWriteObject *object) :
19 _cow_object(object)
20{
21 if (_cow_object != nullptr) {
22 _cow_object->cache_ref();
23 }
24}
25
26/**
27 *
28 */
29INLINE CopyOnWritePointer::
30CopyOnWritePointer(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 */
41INLINE void CopyOnWritePointer::
42operator = (const CopyOnWritePointer &copy) {
43 operator = (copy._cow_object);
44}
45
46/**
47 *
48 */
49INLINE void CopyOnWritePointer::
50operator = (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 */
65INLINE CopyOnWritePointer::
66~CopyOnWritePointer() {
67 if (_cow_object != nullptr) {
68 cache_unref_delete(_cow_object);
69 }
70}
71
72/**
73 *
74 */
75INLINE CopyOnWritePointer::
76CopyOnWritePointer(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 */
86INLINE CopyOnWritePointer::
87CopyOnWritePointer(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 */
101INLINE void CopyOnWritePointer::
102operator = (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 */
118INLINE void CopyOnWritePointer::
119operator = (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 */
138INLINE bool CopyOnWritePointer::
139operator == (const CopyOnWritePointer &other) const {
140 return _cow_object == other._cow_object;
141}
142
143/**
144 *
145 */
146INLINE bool CopyOnWritePointer::
147operator != (const CopyOnWritePointer &other) const {
148 return _cow_object != other._cow_object;
149}
150
151/**
152 *
153 */
154INLINE bool CopyOnWritePointer::
155operator < (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 */
167get_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 */
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 */
204 return _cow_object;
205}
206
207/**
208 * Returns true if the CopyOnWritePointer contains a NULL pointer, false
209 * otherwise.
210 */
212is_null() const {
213 return (_cow_object == nullptr);
214}
215
216/**
217 * Sets the pointer to NULL.
218 */
220clear() {
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 */
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 */
243 nassertr(_cow_object != nullptr, false);
244 return _cow_object->test_ref_count_nonzero();
245}
246
247#ifndef CPPPARSER
248/**
249 *
250 */
251template<class T>
253CopyOnWritePointerTo(To *object) : CopyOnWritePointer(object) {
254}
255#endif // CPPPARSER
256
257#ifndef CPPPARSER
258/**
259 *
260 */
261template<class T>
265{
266}
267#endif // CPPPARSER
268
269#ifndef CPPPARSER
270/**
271 *
272 */
273template<class T>
276 CopyOnWritePointer::operator = (copy);
277}
278#endif // CPPPARSER
279
280#ifndef CPPPARSER
281/**
282 *
283 */
284template<class T>
286operator = (To *object) {
287 CopyOnWritePointer::operator = (object);
288}
289#endif // CPPPARSER
290
291#ifndef CPPPARSER
292/**
293 *
294 */
295template<class T>
299{
300}
301#endif // CPPPARSER
302
303#ifndef CPPPARSER
304/**
305 *
306 */
307template<class T>
309CopyOnWritePointerTo(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 */
324template<class T>
326operator = (CopyOnWritePointerTo<T> &&from) noexcept {
327 CopyOnWritePointer::operator = ((CopyOnWritePointer &&)from);
328}
329#endif // CPPPARSER
330
331#ifndef CPPPARSER
332/**
333 *
334 */
335template<class T>
337operator = (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 */
359template<class T>
360INLINE CPT(typename CopyOnWritePointerTo<T>::To) CopyOnWritePointerTo<T>::
361get_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;
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 */
374template<class T>
375INLINE const typename CopyOnWritePointerTo<T>::To *CopyOnWritePointerTo<T>::
376get_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 */
387template<class T>
388INLINE PT(typename CopyOnWritePointerTo<T>::To) CopyOnWritePointerTo<T>::
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;
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 */
402template<class T>
403INLINE typename CopyOnWritePointerTo<T>::To *CopyOnWritePointerTo<T>::
406}
407#endif // COW_THREADED
408#endif // CPPPARSER
409
410#ifndef CPPPARSER
411/**
412 * See CopyOnWritePointer::get_unsafe_pointer().
413 */
414template<class T>
415INLINE typename CopyOnWritePointerTo<T>::To *CopyOnWritePointerTo<T>::
418}
419#endif // CPPPARSER
void cache_unref_delete(RefCountType *ptr)
This global helper function will unref the given ReferenceCount object, and if the reference count re...
void cache_ref() const
Explicitly increments the cache reference count and the normal reference count simultaneously.
get_cache_ref_count
Returns the current reference count.
void cache_ref_only() const
Decrements the cache reference count without affecting the normal reference count.
bool test_ref_count_integrity() const
Does some easy checks to make sure that the reference count isn't completely bogus.
This base class provides basic reference counting, but also can be used with a CopyOnWritePointer to ...
A template wrapper around the above class, mainly to handle the little typecasting niceties.
To * get_unsafe_pointer()
See CopyOnWritePointer::get_unsafe_pointer().
To * get_write_pointer()
See CopyOnWritePointer::get_write_pointer().
const To * get_read_pointer(Thread *current_thread=Thread::get_current_thread()) const
See CopyOnWritePointer::get_read_pointer().
This safely stores the primary, owned pointer to a CopyOnWriteObject.
bool is_null() const
Returns true if the CopyOnWritePointer contains a NULL pointer, false otherwise.
const CopyOnWriteObject * get_read_pointer(Thread *current_thread) const
Returns a pointer locked for read.
bool test_ref_count_integrity() const
Does some easy checks to make sure that the reference count isn't completely bogus.
CopyOnWriteObject * get_unsafe_pointer()
Returns an unlocked pointer that you can write to.
bool test_ref_count_nonzero() const
Does some easy checks to make sure that the reference count isn't zero, or completely bogus.
CopyOnWriteObject * get_write_pointer()
Returns a pointer locked for write.
void clear()
Sets the pointer to NULL.
This file defines the classes PointerTo and ConstPointerTo (and their abbreviations,...
Definition pointerTo.h:69
bool test_ref_count_nonzero() const
Does some easy checks to make sure that the reference count isn't zero, or completely bogus.
A thread; that is, a lightweight process.
Definition thread.h:46