fallacy_arc/
weak.rs

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