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 true, 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>
460 INLINE bool WeakPointerToBase<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>
469 INLINE bool WeakPointerToBase<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>
479 INLINE bool WeakPointerToBase<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>
489 INLINE bool WeakPointerToBase<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>
499 INLINE bool WeakPointerToBase<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>
508 INLINE bool WeakPointerToBase<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>
517 INLINE bool WeakPointerToBase<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>
572 INLINE bool WeakPointerToBase<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>
596 INLINE bool WeakPointerToBase<T>::
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>
609 INLINE bool WeakPointerToBase<T>::
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>
622 INLINE void WeakPointerToBase<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>
643 INLINE void WeakPointerToBase<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>
655 INLINE void WeakPointerToBase<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 }
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...
void clear()
A convenient way to set the PointerTo object to NULL.
void ref() const
Increases the number of weak references.
This is the base class for PointerTo and ConstPointerTo.
Definition: pointerToBase.h:29
bool was_deleted() const
Returns true if the object represented has been deleted, ie.
This is an object shared by all the weak pointers that point to the same ReferenceCount object.
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
void output(std::ostream &out) const
A handy function to output PointerTo's as a hex pointer followed by a reference count.
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:81
This is the base class for PointerTo and ConstPointerTo.
bool unref() const
Decreases the number of weak references.