Skip to main content

magicstatemachines/shared/weak/
mod.rs

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