misty_vm/
states.rs

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}