1use std::cmp::Reverse;
26use std::marker::PhantomData;
27use std::ops::{Deref, DerefMut};
28use std::sync::{Arc, Mutex};
29use std::time::{Duration, Instant};
30
31use crate::assembly::{TriggerId, TriggerLike};
32use crate::*;
33
34use vecmap::{Entry, VecMap};
35
36pub struct LogicalAction<T: Sync>(pub(crate) Action<Logical, T>);
38
39pub struct PhysicalAction<T: Sync>(pub(crate) Action<Physical, T>);
43
44pub(crate) struct Logical;
45pub(crate) struct Physical;
46
47pub(crate) struct Action<Kind, T: Sync> {
48 pub(crate) min_delay: Duration,
49 id: TriggerId,
50 _logical: PhantomData<Kind>,
52
53 map: VecMap<Reverse<EventTag>, Option<T>>,
58}
59
60impl<K, T: Sync> Action<K, T> {
61 #[inline]
67 pub(crate) fn schedule_future_value(&mut self, time: EventTag, value: Option<T>) {
68 match self.map.entry(Reverse(time)) {
69 Entry::Vacant(e) => e.insert(value),
70 Entry::Occupied(ref mut e) => {
71 trace!("Value overwritten in an action for tag {}", time);
72 trace!("This means an action was scheduled several times for the same tag.");
73 e.replace(value)
74 }
75 }
76 }
77
78 #[inline]
79 pub(crate) fn forget_value(&mut self, time: &EventTag) -> Option<T> {
80 self.map.remove(&Reverse(*time)).flatten()
81 }
82
83 fn new_impl(id: TriggerId, min_delay: Option<Duration>, _is_logical: bool) -> Self {
84 Action {
85 min_delay: min_delay.unwrap_or(Duration::ZERO),
86 id,
88 _logical: PhantomData,
89 map: VecMap::new(),
90 }
91 }
92}
93
94impl<T: Sync, K> ReactionTrigger<T> for Action<K, T> {
95 #[inline]
96 fn is_present(&self, now: &EventTag, _start: &Instant) -> bool {
97 self.map.contains_key(&Reverse(*now))
98 }
99
100 #[inline]
101 fn get_value(&self, now: &EventTag, _start: &Instant) -> Option<T>
102 where
103 T: Copy,
104 {
105 self.map.get(&Reverse(*now)).cloned().flatten()
106 }
107
108 #[inline]
109 fn use_value_ref<O>(&self, now: &EventTag, _start: &Instant, action: impl FnOnce(Option<&T>) -> O) -> O {
110 let inmap: Option<&Option<T>> = self.map.get(&Reverse(*now));
111 let v = inmap.and_then(|i| i.as_ref());
112 action(v)
113 }
114}
115
116#[cfg(not(feature = "no-unsafe"))]
117impl<T: Sync, K> triggers::ReactionTriggerWithRefAccess<T> for Action<K, T> {
118 fn get_value_ref(&self, now: &EventTag, _start: &Instant) -> Option<&T> {
119 self.map.get(&Reverse(*now)).and_then(|a| a.as_ref())
120 }
121}
122
123impl<T: Sync> ReactionTrigger<T> for LogicalAction<T> {
124 #[inline]
125 fn is_present(&self, now: &EventTag, start: &Instant) -> bool {
126 self.0.is_present(now, start)
127 }
128
129 #[inline]
130 fn get_value(&self, now: &EventTag, start: &Instant) -> Option<T>
131 where
132 T: Copy,
133 {
134 self.0.get_value(now, start)
135 }
136
137 #[inline]
138 fn use_value_ref<O>(&self, now: &EventTag, start: &Instant, action: impl FnOnce(Option<&T>) -> O) -> O {
139 self.0.use_value_ref(now, start, action)
140 }
141}
142
143#[cfg(not(feature = "no-unsafe"))]
144impl<T: Sync> triggers::ReactionTriggerWithRefAccess<T> for LogicalAction<T> {
145 fn get_value_ref(&self, now: &EventTag, start: &Instant) -> Option<&T> {
146 self.0.get_value_ref(now, start)
147 }
148}
149
150impl<T: Sync> LogicalAction<T> {
151 pub(crate) fn new(id: TriggerId, min_delay: Option<Duration>) -> Self {
152 Self(Action::new_impl(id, min_delay, true))
153 }
154}
155
156impl<T: Sync> PhysicalAction<T> {
157 fn new(id: TriggerId, min_delay: Option<Duration>) -> Self {
158 Self(Action::new_impl(id, min_delay, false))
159 }
160}
161
162impl<T: Sync> TriggerLike for PhysicalAction<T> {
163 fn get_id(&self) -> TriggerId {
164 self.0.id
165 }
166}
167
168impl<T: Sync> TriggerLike for LogicalAction<T> {
169 fn get_id(&self) -> TriggerId {
170 self.0.id
171 }
172}
173#[derive(Clone)]
231pub struct PhysicalActionRef<T: Sync>(Arc<Mutex<PhysicalAction<T>>>);
232
233impl<T: Sync> PhysicalActionRef<T> {
234 pub(crate) fn new(id: TriggerId, min_delay: Option<Duration>) -> Self {
235 Self(Arc::new(Mutex::new(PhysicalAction::new(id, min_delay))))
236 }
237
238 pub(crate) fn use_mut<O>(&self, f: impl FnOnce(&mut PhysicalAction<T>) -> O) -> Result<O, ()> {
239 let mut refmut = self.0.deref().lock().map_err(|_| ())?;
240
241 Ok(f(refmut.deref_mut()))
242 }
243
244 pub(crate) fn use_mut_p<O, P>(&self, p: P, f: impl FnOnce(&mut PhysicalAction<T>, P) -> O) -> Result<O, P> {
245 match self.0.deref().lock() {
246 Ok(mut refmut) => Ok(f(refmut.deref_mut(), p)),
247 Err(_) => Err(p),
248 }
249 }
250
251 pub(crate) fn use_value<O>(&self, f: impl FnOnce(&PhysicalAction<T>) -> O) -> Result<O, ()> {
252 let r#ref = self.0.deref().lock().map_err(|_| ())?;
253
254 Ok(f(r#ref.deref()))
255 }
256}
257
258impl<T: Sync> TriggerLike for PhysicalActionRef<T> {
259 fn get_id(&self) -> TriggerId {
260 self.use_value(|a| a.get_id()).unwrap()
261 }
262}
263
264impl<T: Sync> ReactionTrigger<T> for PhysicalActionRef<T> {
265 fn is_present(&self, now: &EventTag, start: &Instant) -> bool {
266 self.use_value(|a| a.0.is_present(now, start)).unwrap()
267 }
268
269 fn get_value(&self, now: &EventTag, start: &Instant) -> Option<T>
270 where
271 T: Copy,
272 {
273 self.use_value(|a| a.0.get_value(now, start)).unwrap()
274 }
275
276 fn use_value_ref<O>(&self, now: &EventTag, start: &Instant, action: impl FnOnce(Option<&T>) -> O) -> O {
277 self.use_value(|a| a.0.use_value_ref(now, start, action)).unwrap()
278 }
279}