Skip to main content

magicstatemachines/shared/weak/
mod.rs

1#[cfg(feature = "std")]
2use super::{MutexStorage, RwLockStorage};
3use super::{RefCellStorage, SArc, SRc, SharedState, SharedStorage};
4use alloc::rc::{Rc, Weak as RcWeak};
5use alloc::sync::{Arc, Weak as ArcWeak};
6use core::marker::PhantomData;
7
8/// Weak counterpart to [`SRc`].
9///
10/// A weak handle must be upgraded before borrowing. This keeps "the shared
11/// value was dropped" separate from the existing state/storage borrow errors.
12///
13/// ```ignore
14/// let shared = SRcRefCell::<Connection>::new::<Disconnected>(connection);
15/// let weak = shared.downgrade();
16///
17/// if let Some(shared) = weak.upgrade() {
18///     let disconnected = shared.borrow::<Disconnected>()?;
19/// }
20/// ```
21pub struct WeakSRc<Storage, T>
22where
23    Storage: SharedStorage,
24{
25    storage: RcWeak<Storage::Storage<T>>,
26    backend: PhantomData<fn() -> Storage>,
27    value: PhantomData<fn() -> T>,
28}
29
30/// Weak counterpart to [`SArc`].
31///
32/// A weak handle must be upgraded before borrowing. This keeps "the shared
33/// value was dropped" separate from the existing state/storage borrow errors.
34///
35/// ```ignore
36/// let shared = SArcMutex::<Connection>::new::<Disconnected>(connection);
37/// let weak = shared.downgrade();
38///
39/// match weak.upgrade() {
40///     Some(shared) => {
41///         let disconnected = shared.borrow::<Disconnected>()?;
42///     }
43///     None => {
44///         // All strong handles were dropped.
45///     }
46/// }
47/// ```
48pub struct WeakSArc<Storage, T>
49where
50    Storage: SharedStorage,
51{
52    storage: ArcWeak<Storage::Storage<T>>,
53    backend: PhantomData<fn() -> Storage>,
54    value: PhantomData<fn() -> T>,
55}
56
57impl<Storage, T> Clone for WeakSRc<Storage, T>
58where
59    Storage: SharedStorage,
60{
61    fn clone(&self) -> Self {
62        Self {
63            storage: self.storage.clone(),
64            backend: PhantomData,
65            value: PhantomData,
66        }
67    }
68}
69
70impl<Storage, T> Clone for WeakSArc<Storage, T>
71where
72    Storage: SharedStorage,
73{
74    fn clone(&self) -> Self {
75        Self {
76            storage: self.storage.clone(),
77            backend: PhantomData,
78            value: PhantomData,
79        }
80    }
81}
82
83impl<Storage, T> SharedState<Rc<Storage::Storage<T>>, Storage, T>
84where
85    Storage: SharedStorage,
86{
87    /// Creates a weak handle to this `Rc`-backed shared state.
88    ///
89    /// The weak handle remembers the same [`SharedStorage`] backend as the strong
90    /// handle. After upgrade, callers use the normal `borrow` and `borrow_mut`
91    /// APIs, so state mismatches and backend borrow errors are still reported by
92    /// those APIs:
93    ///
94    /// ```ignore
95    /// let shared = SRcRefCell::<Connection>::new::<Disconnected>(connection);
96    /// let weak: WeakSRcRefCell<Connection> = shared.downgrade();
97    ///
98    /// let shared = weak.upgrade().expect("at least one strong handle remains");
99    /// let disconnected = shared.borrow::<Disconnected>()?;
100    /// ```
101    #[must_use]
102    pub fn downgrade(&self) -> WeakSRc<Storage, T> {
103        WeakSRc {
104            storage: Rc::downgrade(&self.storage),
105            backend: PhantomData,
106            value: PhantomData,
107        }
108    }
109}
110
111impl<Storage, T> SharedState<Arc<Storage::Storage<T>>, Storage, T>
112where
113    Storage: SharedStorage,
114{
115    /// Creates a weak handle to this `Arc`-backed shared state.
116    ///
117    /// Upgrade failure means all strong `Arc` handles were dropped. It is not a
118    /// state-machine error and it is independent from wrong-state or lock errors:
119    ///
120    /// ```ignore
121    /// let shared = SArcMutex::<Connection>::new::<Disconnected>(connection);
122    /// let weak: WeakSArcMutex<Connection> = shared.downgrade();
123    ///
124    /// if let Some(shared) = weak.upgrade() {
125    ///     let disconnected = shared.borrow::<Disconnected>()?;
126    /// }
127    /// ```
128    #[must_use]
129    pub fn downgrade(&self) -> WeakSArc<Storage, T> {
130        WeakSArc {
131            storage: Arc::downgrade(&self.storage),
132            backend: PhantomData,
133            value: PhantomData,
134        }
135    }
136}
137
138impl<Storage, T> WeakSRc<Storage, T>
139where
140    Storage: SharedStorage,
141{
142    /// Attempts to recover a strong `Rc`-backed shared-state handle.
143    ///
144    /// `None` means no strong [`SRc`] handle exists anymore. `Some` does not imply
145    /// the requested state is currently available; use `borrow::<State>()` on the
146    /// upgraded value to perform the state check.
147    #[must_use]
148    pub fn upgrade(&self) -> Option<SRc<Storage, T>> {
149        self.storage.upgrade().map(|storage| SharedState {
150            storage,
151            backend: PhantomData,
152            value: PhantomData,
153        })
154    }
155}
156
157impl<Storage, T> WeakSArc<Storage, T>
158where
159    Storage: SharedStorage,
160{
161    /// Attempts to recover a strong `Arc`-backed shared-state handle.
162    ///
163    /// This mirrors [`std::sync::Weak::upgrade`]. A successful upgrade only
164    /// restores ownership of the shared container; typestate validation still
165    /// happens at the later `borrow`/`borrow_mut` call.
166    #[must_use]
167    pub fn upgrade(&self) -> Option<SArc<Storage, T>> {
168        self.storage.upgrade().map(|storage| SharedState {
169            storage,
170            backend: PhantomData,
171            value: PhantomData,
172        })
173    }
174}
175
176/// Weak handle for [`SRcRefCell`](crate::SRcRefCell).
177///
178/// Use this alias when the strong handle has type `SRcRefCell<T>`.
179pub type WeakSRcRefCell<T> = WeakSRc<RefCellStorage, T>;
180/// Weak handle for [`SArcMutex`](crate::SArcMutex).
181///
182/// Use this alias when the strong handle has type `SArcMutex<T>`.
183#[cfg(feature = "std")]
184pub type WeakSArcMutex<T> = WeakSArc<MutexStorage, T>;
185/// Weak handle for [`SArcRwLock`](crate::SArcRwLock).
186///
187/// Use this alias when the strong handle has type `SArcRwLock<T>`.
188#[cfg(feature = "std")]
189pub type WeakSArcRwLock<T> = WeakSArc<RwLockStorage, T>;