Skip to main content

maolan_engine/
state.rs

1use crate::track::Track;
2use std::{
3    cell::UnsafeCell,
4    collections::HashMap,
5    fmt,
6    marker::PhantomData,
7    ops::{Deref, DerefMut},
8    sync::Arc,
9};
10
11pub type TrackHandle = Arc<Track>;
12pub type StateSlot = arc_swap::ArcSwap<StateSnapshot>;
13
14pub struct State {
15    inner: UnsafeCell<StateData>,
16}
17
18#[derive(Default, Debug)]
19pub struct StateData {
20    pub tracks: HashMap<String, TrackHandle>,
21}
22
23pub struct StateGuard<'a> {
24    ptr: *mut StateData,
25    _marker: PhantomData<&'a mut StateData>,
26}
27
28unsafe impl Send for StateGuard<'_> {}
29
30// SAFETY: `State` preserves the legacy engine invariant that mutation is
31// externally serialized by the control/runtime path. `lock` returns a guard to
32// make interior mutation explicit without retagging a shared reference as
33// unique, which Miri rightfully rejects.
34unsafe impl Sync for State {}
35
36impl Default for State {
37    fn default() -> Self {
38        Self {
39            inner: UnsafeCell::new(StateData::default()),
40        }
41    }
42}
43
44impl fmt::Debug for State {
45    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
46        f.debug_struct("State")
47            .field("tracks", &self.tracks)
48            .finish()
49    }
50}
51
52impl Deref for State {
53    type Target = StateData;
54
55    fn deref(&self) -> &Self::Target {
56        unsafe { &*self.inner.get() }
57    }
58}
59
60impl DerefMut for State {
61    fn deref_mut(&mut self) -> &mut Self::Target {
62        self.inner.get_mut()
63    }
64}
65
66impl StateData {
67    pub fn snapshot(&self) -> StateSnapshot {
68        StateSnapshot {
69            tracks: self.tracks.clone(),
70        }
71    }
72}
73
74impl Deref for StateGuard<'_> {
75    type Target = StateData;
76
77    fn deref(&self) -> &Self::Target {
78        unsafe { &*self.ptr }
79    }
80}
81
82impl DerefMut for StateGuard<'_> {
83    fn deref_mut(&mut self) -> &mut Self::Target {
84        unsafe { &mut *self.ptr }
85    }
86}
87
88#[derive(Clone, Default, Debug)]
89pub struct StateSnapshot {
90    pub tracks: HashMap<String, TrackHandle>,
91}
92
93impl State {
94    pub fn lock(&self) -> StateGuard<'_> {
95        StateGuard {
96            ptr: self.inner.get(),
97            _marker: PhantomData,
98        }
99    }
100
101    pub fn snapshot(&self) -> StateSnapshot {
102        StateData::snapshot(self)
103    }
104}
105
106#[cfg(test)]
107mod tests {
108    use super::*;
109
110    #[test]
111    fn state_default_creates_empty() {
112        let state = State::default();
113        assert!(state.lock().tracks.is_empty());
114    }
115
116    #[test]
117    fn state_debug_format() {
118        let state = State::default();
119        let debug_str = format!("{:?}", state);
120        assert!(debug_str.contains("State"));
121        assert!(debug_str.contains("tracks"));
122    }
123
124    #[test]
125    fn state_new_is_default() {
126        let state1 = State::default();
127        let state2 = State::default();
128        assert_eq!(state1.lock().tracks.len(), state2.lock().tracks.len());
129    }
130
131    #[test]
132    fn state_snapshot_clones_track_handles() {
133        let state = State::default();
134        let track = Arc::new(Track::new("track".to_string(), 1, 1, 0, 0, 64, 48_000.0));
135        state
136            .lock()
137            .tracks
138            .insert("track".to_string(), track.clone());
139
140        let snapshot = state.snapshot();
141
142        assert!(Arc::ptr_eq(snapshot.tracks.get("track").unwrap(), &track));
143    }
144}