1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103
use crate::arc::Arc;
use std::fmt;
use std::sync::Weak as StdWeak;
/// `Weak` is a version of [`Arc`] that holds a non-owning reference to the
/// managed allocation. The allocation is accessed by calling [`upgrade`] on the `Weak`
/// pointer, which returns an <code>[Option]<[Arc]\<T>></code>.
///
/// Since a `Weak` reference does not count towards ownership, it will not
/// prevent the value stored in the allocation from being dropped, and `Weak` itself makes no
/// guarantees about the value still being present. Thus it may return [`None`]
/// when [`upgrade`]d. Note however that a `Weak` reference *does* prevent the allocation
/// itself (the backing store) from being deallocated.
///
/// A `Weak` pointer is useful for keeping a temporary reference to the allocation
/// managed by [`Arc`] without preventing its inner value from being dropped. It is also used to
/// prevent circular references between [`Arc`] pointers, since mutual owning references
/// would never allow either [`Arc`] to be dropped. For example, a tree could
/// have strong [`Arc`] pointers from parent nodes to children, and `Weak`
/// pointers from children back to their parents.
///
/// The typical way to obtain a `Weak` pointer is to call [`Arc::downgrade`].
///
/// [`upgrade`]: Weak::upgrade
#[derive(Clone, Default)]
#[repr(transparent)]
pub struct Weak<T: ?Sized>(StdWeak<T>);
impl<T> Weak<T> {
/// Constructs a new `Weak<T>`, without allocating any memory.
/// Calling [`upgrade`] on the return value always gives [`None`].
///
/// [`upgrade`]: Weak::upgrade
#[must_use]
pub fn new() -> Weak<T> {
Weak(StdWeak::new())
}
}
impl<T: ?Sized> Weak<T> {
#[inline]
pub fn into_std(self) -> StdWeak<T> {
self.0
}
#[inline]
pub fn from_std(w: StdWeak<T>) -> Self {
Weak(w)
}
/// Attempts to upgrade the `Weak` pointer to an [`Arc`], delaying
/// dropping of the inner value if successful.
///
/// Returns [`None`] if the inner value has since been dropped.
#[must_use = "this returns a new `Arc`, \
without modifying the original weak pointer"]
#[inline]
pub fn upgrade(&self) -> Option<Arc<T>> {
self.0.upgrade().map(Arc::from_std)
}
/// Gets the number of strong (`Arc`) pointers pointing to this allocation.
///
/// If `self` was created using [`Weak::new`], this will return 0.
#[must_use]
#[inline]
pub fn strong_count(&self) -> usize {
self.0.strong_count()
}
/// Gets an approximation of the number of `Weak` pointers pointing to this
/// allocation.
///
/// If `self` was created using [`Weak::new`], or if there are no remaining
/// strong pointers, this will return 0.
///
/// # Accuracy
///
/// Due to implementation details, the returned value can be off by 1 in
/// either direction when other threads are manipulating any `Arc`s or
/// `Weak`s pointing to the same allocation.
#[must_use]
#[inline]
pub fn weak_count(&self) -> usize {
self.0.weak_count()
}
/// Returns `true` if the two `Weak`s point to the same allocation (similar to
/// [`std::ptr::eq`]), or if both don't point to any allocation
/// (because they were created with `Weak::new()`).
#[inline]
#[must_use]
pub fn ptr_eq(&self, other: &Self) -> bool {
self.0.ptr_eq(&other.0)
}
}
impl<T: ?Sized + fmt::Debug> fmt::Debug for Weak<T> {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Debug::fmt(&self.0, f)
}
}