1use std::{
2 any::{Any, TypeId},
3 cell::RefCell,
4 collections::{HashMap, HashSet},
5 fmt::Debug,
6 marker::PhantomData,
7 sync::{Arc, RwLock, RwLockReadGuard, RwLockWriteGuard, Weak},
8};
9
10use thread_local::ThreadLocal;
11
12use crate::{
13 client::{AsMistyClientHandle, AsReadonlyMistyClientHandle, MistyClientInner},
14 utils::extend_lifetime,
15};
16
17#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
18pub struct MistyStateId(TypeId);
19
20impl MistyStateId {
21 pub fn new(id: TypeId) -> Self {
22 Self(id)
23 }
24}
25
26pub trait MistyStateTrait: Any + Default + Send + Sync + 'static {
27 fn id() -> MistyStateId {
28 MistyStateId::new(std::any::TypeId::of::<Self>())
29 }
30
31 fn map<'a, R>(cx: impl AsReadonlyMistyClientHandle<'a>, func: impl FnOnce(&Self) -> R) -> R {
32 let states = cx.readonly_handle().inner.state_manager.states();
33 let binding = states.get::<Self>();
34 let state = binding.downcast();
35 let ret = func(state.get());
36 ret
37 }
38
39 fn update<'a, R: 'static>(
40 cx: impl AsMistyClientHandle<'a>,
41 func: impl FnOnce(&mut Self) -> R,
42 ) -> R {
43 let client_ref = cx.handle();
44 let can_update = client_ref.inner.state_manager.can_update();
45 if !can_update {
46 let typ_name = std::any::type_name::<Self>();
47 let pid = std::thread::current().id();
48 panic!("[{:?}] cannot update state {} in this stage", pid, typ_name);
49 }
50
51 client_ref.inner.state_manager.add_update_state::<Self>();
52 let states = cx.readonly_handle().inner.state_manager.states();
53 let binding = states.get::<Self>();
54 let ret = {
55 let mut state = binding.downcast_mut();
56 func(state.get_mut())
57 };
58 return ret;
59 }
60}
61
62pub trait RefMistyStates {
63 fn state_ids() -> Vec<MistyStateId>;
64 fn extract_refs(cx: &MistyStateManager, handler: impl FnOnce(Self))
65 where
66 Self: Sized;
67}
68
69macro_rules! impl_ref_states_tuple {
70 ($($n:tt, $t:ident),+) => {
71 #[allow(unused_parens)]
72 impl<$($t),+> RefMistyStates for ($(&$t),+)
73 where
74 $($t: MistyStateTrait),+
75 {
76 fn state_ids() -> Vec<MistyStateId> {
77 vec![$($t::id()),+]
78 }
79
80 fn extract_refs(cx: &MistyStateManager, handler: impl FnOnce(Self))
81 where
82 Self: Sized,
83 {
84 let states = cx.states();
85 let t = (
86 $(states.get::<$t>()),+,
87 );
88 let t = (
89 $(t.$n.downcast()),+,
90 );
91 let t = (
92 $(
93 unsafe {
94 extend_lifetime(t.$n.get())
95 }
96 ),+
97 );
98
99 handler(t)
100 }
101 }
102 };
103}
104
105impl_ref_states_tuple!(0, T1);
106impl_ref_states_tuple!(0, T1, 1, T2);
107impl_ref_states_tuple!(0, T1, 1, T2, 2, T3);
108impl_ref_states_tuple!(0, T1, 1, T2, 2, T3, 3, T4);
109impl_ref_states_tuple!(0, T1, 1, T2, 2, T3, 3, T4, 4, T5);
110impl_ref_states_tuple!(0, T1, 1, T2, 2, T3, 3, T4, 4, T5, 5, T6);
111impl_ref_states_tuple!(0, T1, 1, T2, 2, T3, 3, T4, 4, T5, 5, T6, 6, T7);
112impl_ref_states_tuple!(0, T1, 1, T2, 2, T3, 3, T4, 4, T5, 5, T6, 6, T7, 7, T8);
113impl_ref_states_tuple!(0, T1, 1, T2, 2, T3, 3, T4, 4, T5, 5, T6, 6, T7, 7, T8, 8, T9);
114impl_ref_states_tuple!(0, T1, 1, T2, 2, T3, 3, T4, 4, T5, 5, T6, 6, T7, 7, T8, 8, T9, 9, T10);
115impl_ref_states_tuple!(
116 0, T1, 1, T2, 2, T3, 3, T4, 4, T5, 5, T6, 6, T7, 7, T8, 8, T9, 9, T10, 10, T11
117);
118impl_ref_states_tuple!(
119 0, T1, 1, T2, 2, T3, 3, T4, 4, T5, 5, T6, 6, T7, 7, T8, 8, T9, 9, T10, 10, T11, 11, T12
120);
121
122#[derive(Debug, Clone)]
123struct BoxedState {
124 inner: Arc<RwLock<dyn Any + Send + Sync>>,
125}
126
127struct StateRead<'a, T> {
128 inner: RwLockReadGuard<'a, dyn Any + Send + Sync>,
129 _marker: PhantomData<T>,
130}
131
132struct StateWrite<'a, T> {
133 inner: RwLockWriteGuard<'a, dyn Any + Send + Sync>,
134 _marker: PhantomData<T>,
135}
136
137#[derive(Debug)]
138pub struct States {
139 inner: HashMap<MistyStateId, BoxedState>,
140}
141
142#[derive(Debug)]
143pub struct MistyStateManager {
144 states: States,
145 updated_state: ThreadLocal<RefCell<HashSet<MistyStateId>>>,
146 depth: ThreadLocal<RefCell<u32>>,
147}
148
149impl<'a, T: 'static> StateRead<'a, T> {
150 pub fn get(&'a self) -> &'a T {
151 self.inner.downcast_ref().unwrap()
152 }
153}
154
155impl<'a, T: 'static> StateWrite<'a, T> {
156 pub fn get_mut(&mut self) -> &mut T {
157 self.inner.downcast_mut().unwrap()
158 }
159}
160
161impl BoxedState {
162 pub fn new<T: MistyStateTrait>() -> Self {
163 Self {
164 inner: Arc::new(RwLock::new(T::default())),
165 }
166 }
167
168 pub fn downcast<T: MistyStateTrait>(&self) -> StateRead<'_, T> {
169 let state = self.inner.read().unwrap();
170 StateRead {
171 inner: state,
172 _marker: Default::default(),
173 }
174 }
175
176 pub fn downcast_mut<T: MistyStateTrait>(&self) -> StateWrite<'_, T> {
177 let state = self.inner.write().unwrap();
178 StateWrite {
179 inner: state,
180 _marker: Default::default(),
181 }
182 }
183}
184
185impl States {
186 pub fn new() -> Self {
187 Self {
188 inner: Default::default(),
189 }
190 }
191
192 pub fn register<T: MistyStateTrait>(&mut self) {
193 self.inner.insert(T::id(), BoxedState::new::<T>());
194 }
195
196 fn get<T: MistyStateTrait>(&self) -> BoxedState {
197 let v = self.inner.get(&T::id()).unwrap();
198 v.clone()
199 }
200}
201
202impl MistyStateManager {
203 pub fn new(states: States) -> Self {
204 MistyStateManager {
205 states,
206 updated_state: Default::default(),
207 depth: Default::default(),
208 }
209 }
210
211 pub(crate) fn states(&self) -> &States {
212 &self.states
213 }
214
215 pub(crate) fn enter_mut_span(&self) {
216 let mut mut_update = self.depth.get_or_default().borrow_mut();
217 *mut_update += 1;
218 }
219 pub(crate) fn leave_mut_span(&self) -> bool {
220 let mut mut_update = self.depth.get_or_default().borrow_mut();
221 if *mut_update <= 0 {
222 panic!(
223 "[Internal Error] MistyClientThisNotifyState depth is {}",
224 *mut_update
225 );
226 }
227 *mut_update -= 1;
228
229 let is_depth_zero = *mut_update == 0;
230 return is_depth_zero;
231 }
232 pub(crate) fn clear_updated_states(&self) {
233 self.updated_state.get_or_default().borrow_mut().clear();
234 }
235 pub(crate) fn reset(&self) {
236 self.updated_state.get_or_default().borrow_mut().clear();
237 *self.depth.get_or_default().borrow_mut() = 0;
238 }
239 pub(crate) fn can_update(&self) -> bool {
240 return *self.depth.get_or_default().borrow() > 0;
241 }
242
243 pub(crate) fn add_update_state<S: MistyStateTrait>(&self) {
244 self.updated_state
245 .get_or_default()
246 .borrow_mut()
247 .insert(S::id());
248 }
249
250 pub(crate) fn contains_updated_state(&self, state_ids: &Vec<MistyStateId>) -> bool {
251 let states = self.updated_state.get_or_default().borrow();
252 return state_ids
253 .into_iter()
254 .any(|state_id| states.contains(state_id));
255 }
256}
257
258pub(crate) struct GuardCleanupStatesForPanic {
259 inner: Weak<MistyClientInner>,
260 mark: bool,
261}
262impl GuardCleanupStatesForPanic {
263 pub fn new(inner: Weak<MistyClientInner>) -> GuardCleanupStatesForPanic {
264 GuardCleanupStatesForPanic { inner, mark: false }
265 }
266 pub fn mark(&mut self) {
267 self.mark = true;
268 }
269}
270impl Drop for GuardCleanupStatesForPanic {
271 fn drop(&mut self) {
272 if self.mark {
273 return;
274 }
275 if let Some(inner) = self.inner.upgrade() {
276 inner.state_manager.reset();
277 }
278 }
279}