Panda3D
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  */
18 template<class T>
20 WeakPointerToBase(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  */
33 template<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  */
48 template<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  */
66 template<class T>
68 WeakPointerToBase(WeakPointerToBase<T> &&from) noexcept {
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  */
78 template<class T>
79 template<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  */
98 template<class T>
99 template<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  */
115 template<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  */
128 template<class T>
130 reassign(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  */
154 template<class T>
155 INLINE void WeakPointerToBase<T>::
156 reassign(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  */
165 template<class T>
166 INLINE void WeakPointerToBase<T>::
167 reassign(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  */
194 template<class T>
195 INLINE void WeakPointerToBase<T>::
196 reassign(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  */
216 template<class T>
217 template<class Y>
218 INLINE void WeakPointerToBase<T>::
219 reassign(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  */
244 template<class T>
245 template<class Y>
246 INLINE void WeakPointerToBase<T>::
247 reassign(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  */
272 template<class T>
273 INLINE void WeakPointerToBase<T>::
274 update_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  */
296 template<class T>
297 INLINE void WeakPointerToBase<T>::
298 lock_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  */
321 template<class T>
322 INLINE bool WeakPointerToBase<T>::
323 operator == (const To *other) const {
324  return (To *)_void_ptr == other;
325 }
326 
327 /**
328  *
329  */
330 template<class T>
331 INLINE bool WeakPointerToBase<T>::
332 operator != (const To *other) const {
333  return (To *)_void_ptr != other;
334 }
335 
336 /**
337  *
338  */
339 template<class T>
340 INLINE bool WeakPointerToBase<T>::
341 operator > (const To *other) const {
342  return (To *)_void_ptr > other;
343 }
344 
345 /**
346  *
347  */
348 template<class T>
349 INLINE bool WeakPointerToBase<T>::
350 operator <= (const To *other) const {
351  return (To *)_void_ptr <= other;
352 }
353 
354 /**
355  *
356  */
357 template<class T>
358 INLINE bool WeakPointerToBase<T>::
359 operator >= (const To *other) const {
360  return (To *)_void_ptr >= other;
361 }
362 /**
363  *
364  */
365 template<class T>
366 INLINE bool WeakPointerToBase<T>::
367 operator == (To *other) const {
368  return (To *)_void_ptr == other;
369 }
370 
371 /**
372  *
373  */
374 template<class T>
375 INLINE bool WeakPointerToBase<T>::
376 operator != (To *other) const {
377  return (To *)_void_ptr != other;
378 }
379 
380 /**
381  *
382  */
383 template<class T>
384 INLINE bool WeakPointerToBase<T>::
385 operator > (To *other) const {
386  return (To *)_void_ptr > other;
387 }
388 
389 /**
390  *
391  */
392 template<class T>
393 INLINE bool WeakPointerToBase<T>::
394 operator <= (To *other) const {
395  return (To *)_void_ptr <= other;
396 }
397 
398 /**
399  *
400  */
401 template<class T>
402 INLINE bool WeakPointerToBase<T>::
403 operator >= (To *other) const {
404  return (To *)_void_ptr >= other;
405 }
406 
407 /**
408  *
409  */
410 template<class T>
411 INLINE bool WeakPointerToBase<T>::
412 operator == (std::nullptr_t) const {
413  return _void_ptr == nullptr;
414 }
415 
416 /**
417  *
418  */
419 template<class T>
420 INLINE bool WeakPointerToBase<T>::
421 operator != (std::nullptr_t) const {
422  return _void_ptr != nullptr;
423 }
424 
425 /**
426  *
427  */
428 template<class T>
429 INLINE bool WeakPointerToBase<T>::
430 operator > (std::nullptr_t) const {
431  return _void_ptr != nullptr;
432 }
433 
434 /**
435  *
436  */
437 template<class T>
438 INLINE bool WeakPointerToBase<T>::
439 operator <= (std::nullptr_t) const {
440  return _void_ptr == nullptr;
441 }
442 
443 /**
444  *
445  */
446 template<class T>
447 INLINE bool WeakPointerToBase<T>::
448 operator >= (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  */
459 template<class T>
461 operator == (const WeakPointerToBase<To> &other) const {
462  return (To *)_void_ptr == (To *)other._void_ptr;
463 }
464 
465 /**
466  * @see operator ==
467  */
468 template<class T>
470 operator != (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  */
478 template<class T>
480 operator > (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  */
488 template<class T>
490 operator <= (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  */
498 template<class T>
500 operator >= (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  */
507 template<class T>
509 operator == (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  */
516 template<class T>
518 operator != (const PointerToBase<To> &other) const {
519  return (To *)_void_ptr != (To *)((WeakPointerToBase<To> *)&other)->_void_ptr;
520 }
521 
522 /**
523  *
524  */
525 template<class T>
526 INLINE bool WeakPointerToBase<T>::
527 operator > (const PointerToBase<To> &other) const {
528  return (To *)_void_ptr > (To *)((WeakPointerToBase<To> *)&other)->_void_ptr;
529 }
530 
531 /**
532  *
533  */
534 template<class T>
535 INLINE bool WeakPointerToBase<T>::
536 operator <= (const PointerToBase<To> &other) const {
537  return (To *)_void_ptr <= (To *)((WeakPointerToBase<To> *)&other)->_void_ptr;
538 }
539 
540 /**
541  *
542  */
543 template<class T>
544 INLINE bool WeakPointerToBase<T>::
545 operator >= (const PointerToBase<To> &other) const {
546  return (To *)_void_ptr >= (To *)((WeakPointerToBase<To> *)&other)->_void_ptr;
547 }
548 
549 /**
550  *
551  */
552 template<class T>
553 INLINE bool WeakPointerToBase<T>::
554 operator < (const To *other) const {
555  return (To *)_void_ptr < other;
556 }
557 
558 /**
559  *
560  */
561 template<class T>
562 INLINE bool WeakPointerToBase<T>::
563 operator < (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  */
571 template<class T>
573 operator < (const WeakPointerToBase<To> &other) const {
574  return (To *)_void_ptr < (To *)other._void_ptr;
575 }
576 
577 /**
578  *
579  */
580 template<class T>
581 INLINE bool WeakPointerToBase<T>::
582 operator < (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  */
594 template<class T>
595 template<class Y>
597 owner_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  */
607 template<class T>
608 template<class Y>
610 owner_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  */
621 template<class T>
623 clear() {
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  */
642 template<class T>
644 refresh() 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  */
654 template<class T>
656 output(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 }
WeakPointerToBase::output
void output(std::ostream &out) const
A handy function to output PointerTo's as a hex pointer followed by a reference count.
Definition: weakPointerToBase.I:656
WeakPointerToBase
This is the base class for PointerTo and ConstPointerTo.
Definition: weakPointerToBase.h:26
WeakPointerToBase::refresh
void refresh() const
Informs the WeakPointerTo object that its pointer is no longer deleted.
Definition: weakPointerToBase.I:644
WeakPointerToBase::owner_before
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...
Definition: weakPointerToBase.I:597
WeakReferenceList::ref
void ref() const
Increases the number of weak references.
Definition: weakReferenceList.I:20
TypeHandle
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:81
MemoryUsage::update_type
static void update_type(ReferenceCount *ptr, TypeHandle type)
Associates the indicated type with the given pointer.
Definition: memoryUsage.I:55
PointerToBase
This is the base class for PointerTo and ConstPointerTo.
Definition: pointerToBase.h:29
WeakReferenceList::was_deleted
bool was_deleted() const
Returns true if the object represented has been deleted, ie.
Definition: weakReferenceList.I:43
MemoryUsage::get_track_memory_usage
static bool get_track_memory_usage()
Returns true if the user has Configured the variable 'track-memory-usage' to true,...
Definition: memoryUsage.I:20
WeakReferenceList
This is an object shared by all the weak pointers that point to the same ReferenceCount object.
Definition: weakReferenceList.h:29
WeakReferenceList::unref
bool unref() const
Decreases the number of weak references.
Definition: weakReferenceList.I:32
WeakPointerToBase::clear
void clear()
A convenient way to set the PointerTo object to NULL.
Definition: weakPointerToBase.I:623