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}