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