Panda3D
Loading...
Searching...
No Matches
weakPointerToBase.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 weakPointerToBase.I
10 * @author drose
11 * @date 2004-09-27
12 */
13
14/**
15 * Constructs a weak pointer from a plain pointer (or nullptr). It is the
16 * caller's responsibility to ensure that it points to a valid object.
17 */
18template<class T>
20WeakPointerToBase(To *ptr) {
21 _void_ptr = (To *)ptr;
22 if (ptr != nullptr) {
23 _weak_ref = ptr->weak_ref();
24#ifdef DO_MEMORY_USAGE
25 update_type(ptr);
26#endif
27 }
28}
29
30/**
31 * Constructs a weak pointer from a reference-counting pointer.
32 */
33template<class T>
36 // This double-casting is a bit of a cheat to get around the inheritance
37 // issue--it's difficult to declare a template class to be a friend.
38 To *ptr = (To *)((const WeakPointerToBase<To> *)&copy)->_void_ptr;
39 _void_ptr = ptr;
40 if (ptr != nullptr) {
41 _weak_ref = ptr->weak_ref();
42 }
43}
44
45/**
46 * Copies a weak pointer. This is always safe, even for expired pointers.
47 */
48template<class T>
51 _void_ptr = copy._void_ptr;
52
53 // While it is tempting to stop maintaining the control block pointer after
54 // the object has been deleted, we still need it in order to define a
55 // consistent ordering in owner_before.
56 WeakReferenceList *weak_ref = copy._weak_ref;
57 if (weak_ref != nullptr/* && !weak_ref->was_deleted()*/) {
58 _weak_ref = copy._weak_ref;
59 _weak_ref->ref();
60 }
61}
62
63/**
64 * Moves a weak pointer. This is always safe, even for expired pointers.
65 */
66template<class T>
69 this->_void_ptr = from._void_ptr;
70 this->_weak_ref = from._weak_ref;
71 from._void_ptr = nullptr;
72 from._weak_ref = nullptr;
73}
74
75/**
76 * Copies a weak pointer from a cast-convertible weak pointer type.
77 */
78template<class T>
79template<class Y>
82 // If this next line gives an error, you are trying to convert a WeakPointerTo
83 // from an incompatible type of another WeakPointerTo.
84 To *ptr = (Y *)r._void_ptr;
85
86 this->_void_ptr = ptr;
87
88 WeakReferenceList *weak_ref = r._weak_ref;
89 if (weak_ref != nullptr) {
90 _weak_ref = weak_ref;
91 weak_ref->ref();
92 }
93}
94
95/**
96 * Moves a weak pointer from a cast-convertible weak pointer type.
97 */
98template<class T>
99template<class Y>
102 // If this next line gives an error, you are trying to convert a WeakPointerTo
103 // from an incompatible type of another WeakPointerTo.
104 To *ptr = (Y *)r._void_ptr;
105
106 this->_void_ptr = ptr;
107 this->_weak_ref = r._weak_ref;
108 r._void_ptr = nullptr;
109 r._weak_ref = nullptr;
110}
111
112/**
113 *
114 */
115template<class T>
118 WeakReferenceList *old_ref = (WeakReferenceList *)_weak_ref;
119 if (old_ref != nullptr && !old_ref->unref()) {
120 delete old_ref;
121 }
122}
123
124/**
125 * This is the main work of the PointerTo family. When the pointer is
126 * reassigned, decrement the old reference count and increment the new one.
127 */
128template<class T>
130reassign(To *ptr) {
131 if (ptr != (To *)_void_ptr) {
132 WeakReferenceList *old_ref = (WeakReferenceList *)_weak_ref;
133
134 _void_ptr = (void *)ptr;
135 if (ptr != nullptr) {
136 _weak_ref = ptr->weak_ref();
137#ifdef DO_MEMORY_USAGE
138 update_type(ptr);
139#endif
140 } else {
141 _weak_ref = nullptr;
142 }
143
144 // Now remove the old reference.
145 if (old_ref != nullptr && !old_ref->unref()) {
146 delete old_ref;
147 }
148 }
149}
150
151/**
152 *
153 */
154template<class T>
155INLINE void WeakPointerToBase<T>::
156reassign(const PointerToBase<To> &copy) {
157 // This double-casting is a bit of a cheat to get around the inheritance
158 // issue--it's difficult to declare a template class to be a friend.
159 reassign((To *)((const WeakPointerToBase<To> *)&copy)->_void_ptr);
160}
161
162/**
163 *
164 */
165template<class T>
166INLINE void WeakPointerToBase<T>::
167reassign(const WeakPointerToBase<To> &copy) {
168 void *new_ptr = copy._void_ptr;
169 if (new_ptr != _void_ptr) {
170 WeakReferenceList *old_ref = (WeakReferenceList *)_weak_ref;
171 _void_ptr = new_ptr;
172
173 // While it is tempting to stop maintaining the control block pointer
174 // after the object has been deleted, we still need it in order to define
175 // a consistent ordering in owner_before.
176 WeakReferenceList *weak_ref = copy._weak_ref;
177 if (weak_ref != nullptr/* && !weak_ref->was_deleted()*/) {
178 weak_ref->ref();
179 _weak_ref = weak_ref;
180 } else {
181 _weak_ref = nullptr;
182 }
183
184 // Now remove the old reference.
185 if (old_ref != nullptr && !old_ref->unref()) {
186 delete old_ref;
187 }
188 }
189}
190
191/**
192 *
193 */
194template<class T>
195INLINE void WeakPointerToBase<T>::
196reassign(WeakPointerToBase<To> &&from) noexcept {
197 // Protect against self-move-assignment.
198 if (from._void_ptr != this->_void_ptr) {
199 WeakReferenceList *old_ref = (WeakReferenceList *)this->_weak_ref;
200
201 this->_void_ptr = from._void_ptr;
202 this->_weak_ref = from._weak_ref;
203 from._void_ptr = nullptr;
204 from._weak_ref = nullptr;
205
206 // Now delete the old pointer.
207 if (old_ref != nullptr && !old_ref->unref()) {
208 delete old_ref;
209 }
210 }
211}
212
213/**
214 * Like above, but casts from a compatible pointer type.
215 */
216template<class T>
217template<class Y>
218INLINE void WeakPointerToBase<T>::
219reassign(const WeakPointerToBase<Y> &copy) {
220 // If there is a compile error on this line, it means you tried to assign
221 // an incompatible type.
222 To *new_ptr = (Y *)copy._void_ptr;
223
224 if (new_ptr != (To *)_void_ptr) {
225 WeakReferenceList *old_ref = (WeakReferenceList *)_weak_ref;
226 WeakReferenceList *new_ref = copy._weak_ref;
227 _void_ptr = new_ptr;
228 _weak_ref = new_ref;
229
230 if (new_ref != nullptr) {
231 new_ref->ref();
232 }
233
234 // Now remove the old reference.
235 if (old_ref != nullptr && !old_ref->unref()) {
236 delete old_ref;
237 }
238 }
239}
240
241/**
242 * Like above, but casts from a compatible pointer type.
243 */
244template<class T>
245template<class Y>
246INLINE void WeakPointerToBase<T>::
247reassign(WeakPointerToBase<Y> &&from) noexcept {
248 // Protect against self-move-assignment.
249 if (from._void_ptr != this->_void_ptr) {
250 WeakReferenceList *old_ref = (WeakReferenceList *)this->_weak_ref;
251
252 // If there is a compile error on this line, it means you tried to assign
253 // an incompatible type.
254 To *new_ptr = (Y *)from._void_ptr;
255
256 this->_void_ptr = new_ptr;
257 this->_weak_ref = from._weak_ref;
258 from._void_ptr = nullptr;
259 from._weak_ref = nullptr;
260
261 // Now delete the old pointer.
262 if (old_ref != nullptr && !old_ref->unref()) {
263 delete old_ref;
264 }
265 }
266}
267
268/**
269 * Ensures that the MemoryUsage record for the pointer has the right type of
270 * object, if we know the type ourselves.
271 */
272template<class T>
273INLINE void WeakPointerToBase<T>::
274update_type(To *ptr) {
275#ifdef DO_MEMORY_USAGE
277 TypeHandle type = get_type_handle(To);
278 if (type == TypeHandle::none()) {
279 do_init_type(To);
280 type = get_type_handle(To);
281 }
282 if (type != TypeHandle::none()) {
283 MemoryUsage::update_type(ptr, type);
284 }
285 }
286#endif // DO_MEMORY_USAGE
287}
288
289/**
290 * A thread-safe way to access the underlying pointer; will only write to the
291 * given pointer if the underlying pointer has not yet been deleted and is not
292 * null. Note that it may leave the pointer unassigned even if was_deleted()
293 * still returns false, which can occur if the object has reached reference
294 * count 0 and is about to be destroyed.
295 */
296template<class T>
297INLINE void WeakPointerToBase<T>::
298lock_into(PointerToBase<To> &locked) const {
299 WeakReferenceList *weak_ref = this->_weak_ref;
300 if (weak_ref != nullptr) {
301 weak_ref->_lock.lock();
302 if (!weak_ref->was_deleted()) {
303 // We also need to check that the reference count is not zero (which can
304 // happen if the object is currently being destructed), since that could
305 // cause double deletion.
306 To *plain_ptr = (To *)WeakPointerToBase<T>::_void_ptr;
307 if (plain_ptr != nullptr && plain_ptr->ref_if_nonzero()) {
308 // It is valid and we successfully grabbed a reference. Assign it,
309 // noting we have already incremented the reference count.
310 locked._void_ptr = plain_ptr;
311 }
312 }
313 weak_ref->_lock.unlock();
314 }
315}
316
317#ifndef CPPPARSER
318/**
319 *
320 */
321template<class T>
322INLINE bool WeakPointerToBase<T>::
323operator == (const To *other) const {
324 return (To *)_void_ptr == other;
325}
326
327/**
328 *
329 */
330template<class T>
331INLINE bool WeakPointerToBase<T>::
332operator != (const To *other) const {
333 return (To *)_void_ptr != other;
334}
335
336/**
337 *
338 */
339template<class T>
340INLINE bool WeakPointerToBase<T>::
341operator > (const To *other) const {
342 return (To *)_void_ptr > other;
343}
344
345/**
346 *
347 */
348template<class T>
349INLINE bool WeakPointerToBase<T>::
350operator <= (const To *other) const {
351 return (To *)_void_ptr <= other;
352}
353
354/**
355 *
356 */
357template<class T>
358INLINE bool WeakPointerToBase<T>::
359operator >= (const To *other) const {
360 return (To *)_void_ptr >= other;
361}
362/**
363 *
364 */
365template<class T>
366INLINE bool WeakPointerToBase<T>::
367operator == (To *other) const {
368 return (To *)_void_ptr == other;
369}
370
371/**
372 *
373 */
374template<class T>
375INLINE bool WeakPointerToBase<T>::
376operator != (To *other) const {
377 return (To *)_void_ptr != other;
378}
379
380/**
381 *
382 */
383template<class T>
384INLINE bool WeakPointerToBase<T>::
385operator > (To *other) const {
386 return (To *)_void_ptr > other;
387}
388
389/**
390 *
391 */
392template<class T>
393INLINE bool WeakPointerToBase<T>::
394operator <= (To *other) const {
395 return (To *)_void_ptr <= other;
396}
397
398/**
399 *
400 */
401template<class T>
402INLINE bool WeakPointerToBase<T>::
403operator >= (To *other) const {
404 return (To *)_void_ptr >= other;
405}
406
407/**
408 *
409 */
410template<class T>
411INLINE bool WeakPointerToBase<T>::
412operator == (std::nullptr_t) const {
413 return _void_ptr == nullptr;
414}
415
416/**
417 *
418 */
419template<class T>
420INLINE bool WeakPointerToBase<T>::
421operator != (std::nullptr_t) const {
422 return _void_ptr != nullptr;
423}
424
425/**
426 *
427 */
428template<class T>
429INLINE bool WeakPointerToBase<T>::
430operator > (std::nullptr_t) const {
431 return _void_ptr != nullptr;
432}
433
434/**
435 *
436 */
437template<class T>
438INLINE bool WeakPointerToBase<T>::
439operator <= (std::nullptr_t) const {
440 return _void_ptr == nullptr;
441}
442
443/**
444 *
445 */
446template<class T>
447INLINE bool WeakPointerToBase<T>::
448operator >= (std::nullptr_t) const {
449 return true;
450}
451
452/**
453 * Returns true if both pointers have the same raw pointer value. For this to
454 * be meaningful, neither pointer may have expired, since if one has expired
455 * while the other was allocated at the expired pointer's memory address, this
456 * comparison will be true even though they didn't refer to the same object.
457 * @see owner_before
458 */
459template<class T>
461operator == (const WeakPointerToBase<To> &other) const {
462 return (To *)_void_ptr == (To *)other._void_ptr;
463}
464
465/**
466 * @see operator ==
467 */
468template<class T>
470operator != (const WeakPointerToBase<To> &other) const {
471 return (To *)_void_ptr != (To *)other._void_ptr;
472}
473
474/**
475 * Defines an ordering between WeakPointerTo based on their raw pointer value.
476 * @deprecated Do not use this. Use owner_before or std::owner_less instead.
477 */
478template<class T>
480operator > (const WeakPointerToBase<To> &other) const {
481 return (To *)_void_ptr > (To *)other._void_ptr;
482}
483
484/**
485 * Defines an ordering between WeakPointerTo based on their raw pointer value.
486 * @deprecated Do not use this. Use owner_before or std::owner_less instead.
487 */
488template<class T>
490operator <= (const WeakPointerToBase<To> &other) const {
491 return (To *)_void_ptr <= (To *)other._void_ptr;
492}
493
494/**
495 * Defines an ordering between WeakPointerTo based on their raw pointer value.
496 * @deprecated Do not use this. Use owner_before or std::owner_less instead.
497 */
498template<class T>
500operator >= (const WeakPointerToBase<To> &other) const {
501 return (To *)_void_ptr >= (To *)other._void_ptr;
502}
503
504/**
505 * Returns true if both pointers point to the same object.
506 */
507template<class T>
509operator == (const PointerToBase<To> &other) const {
510 return (To *)_void_ptr == (To *)((WeakPointerToBase<To> *)&other)->_void_ptr;
511}
512
513/**
514 * Returns false if both pointers point to the same object.
515 */
516template<class T>
518operator != (const PointerToBase<To> &other) const {
519 return (To *)_void_ptr != (To *)((WeakPointerToBase<To> *)&other)->_void_ptr;
520}
521
522/**
523 *
524 */
525template<class T>
526INLINE bool WeakPointerToBase<T>::
527operator > (const PointerToBase<To> &other) const {
528 return (To *)_void_ptr > (To *)((WeakPointerToBase<To> *)&other)->_void_ptr;
529}
530
531/**
532 *
533 */
534template<class T>
535INLINE bool WeakPointerToBase<T>::
536operator <= (const PointerToBase<To> &other) const {
537 return (To *)_void_ptr <= (To *)((WeakPointerToBase<To> *)&other)->_void_ptr;
538}
539
540/**
541 *
542 */
543template<class T>
544INLINE bool WeakPointerToBase<T>::
545operator >= (const PointerToBase<To> &other) const {
546 return (To *)_void_ptr >= (To *)((WeakPointerToBase<To> *)&other)->_void_ptr;
547}
548
549/**
550 *
551 */
552template<class T>
553INLINE bool WeakPointerToBase<T>::
554operator < (const To *other) const {
555 return (To *)_void_ptr < other;
556}
557
558/**
559 *
560 */
561template<class T>
562INLINE bool WeakPointerToBase<T>::
563operator < (std::nullptr_t) const {
564 return false;
565}
566
567/**
568 * Defines an ordering between WeakPointerTo based on their raw pointer value.
569 * @deprecated Do not use this. Use owner_before or std::owner_less instead.
570 */
571template<class T>
573operator < (const WeakPointerToBase<To> &other) const {
574 return (To *)_void_ptr < (To *)other._void_ptr;
575}
576
577/**
578 *
579 */
580template<class T>
581INLINE bool WeakPointerToBase<T>::
582operator < (const PointerToBase<To> &other) const {
583 return (To *)_void_ptr < (To *)((WeakPointerToBase<To> *)&other)->_void_ptr;
584}
585
586#endif // CPPPARSER
587
588/**
589 * Defines an ordering that is guaranteed to remain consistent even after the
590 * weak pointers have expired. This may result in two pointers with the same
591 * get_orig() value comparing unequal if one of them is a new object that was
592 * allocated at the same memory address as the older, expired pointer.
593 */
594template<class T>
595template<class Y>
597owner_before(const WeakPointerToBase<Y> &other) const noexcept {
598 return _weak_ref < other._weak_ref;
599}
600
601/**
602 * Defines an ordering that is guaranteed to remain consistent even after this
603 * weak pointer has expired. This may result in two pointers with the same
604 * get_orig() value comparing unequal if one of them is a new object that was
605 * allocated at the same memory address as the older, expired pointer.
606 */
607template<class T>
608template<class Y>
610owner_before(const PointerToBase<Y> &other) const noexcept {
611 // Unfortunately, this may needlessly cause a control block to be allocated,
612 // but I do not see a more efficient solution.
613 return (other._void_ptr != nullptr) &&
614 (_void_ptr == nullptr || _weak_ref < ((const Y *)other._void_ptr)->get_weak_list());
615}
616
617/**
618 * A convenient way to set the PointerTo object to NULL. (Assignment to a NULL
619 * pointer also works, of course.)
620 */
621template<class T>
623clear() {
624 WeakReferenceList *old_ref = (WeakReferenceList *)_weak_ref;
625 _void_ptr = nullptr;
626 _weak_ref = nullptr;
627
628 // Now remove the old reference.
629 if (old_ref != nullptr && !old_ref->unref()) {
630 delete old_ref;
631 }
632}
633
634/**
635 * Informs the WeakPointerTo object that its pointer is no longer deleted.
636 * This may be used after a WeakPointerTo has deleted a deleted pointer, and
637 * then a new pointer has been reallocated. It's equivalent to simply
638 * reassigning the pointer to its new (i.e. original) value, but has the
639 * advantage that it is const, so can be used for WeakPointers used as keys in
640 * STL maps and sets.
641 */
642template<class T>
644refresh() const {
645 if (_void_ptr != nullptr) {
646 ((WeakPointerToBase<T> *)this)->reassign((To *)_void_ptr);
647 }
648}
649
650/**
651 * A handy function to output PointerTo's as a hex pointer followed by a
652 * reference count.
653 */
654template<class T>
656output(std::ostream &out) const {
657 out << _void_ptr;
658
659 WeakReferenceList *weak_ref = this->_weak_ref;
660 if (weak_ref != nullptr) {
661 weak_ref->_lock.lock();
662 if (!weak_ref->was_deleted()) {
663 out << ":" << ((To *)_void_ptr)->get_ref_count();
664 } else {
665 out << ":deleted";
666 }
667 weak_ref->_lock.unlock();
668 } else {
669 out << ":invalid";
670 }
671}
static void update_type(ReferenceCount *ptr, TypeHandle type)
Associates the indicated type with the given pointer.
Definition memoryUsage.I:55
static bool get_track_memory_usage()
Returns true if the user has Configured the variable 'track-memory-usage' to true,...
Definition memoryUsage.I:20
This is the base class for PointerTo and ConstPointerTo.
TypeHandle is the identifier used to differentiate C++ class types.
Definition typeHandle.h:81
This is the base class for PointerTo and ConstPointerTo.
void output(std::ostream &out) const
A handy function to output PointerTo's as a hex pointer followed by a reference count.
void clear()
A convenient way to set the PointerTo object to NULL.
void refresh() const
Informs the WeakPointerTo object that its pointer is no longer deleted.
bool owner_before(const WeakPointerToBase< Y > &other) const noexcept
Defines an ordering that is guaranteed to remain consistent even after the weak pointers have expired...
This is an object shared by all the weak pointers that point to the same ReferenceCount object.
bool was_deleted() const
Returns true if the object represented has been deleted, ie.
void ref() const
Increases the number of weak references.
bool unref() const
Decreases the number of weak references.