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>;