cog_task/action/core/
delayed.rs1use crate::action::{Action, ActionSignal, Props, StatefulAction, DEFAULT};
2use crate::comm::{QWriter, Signal, SignalId};
3use crate::resource::{IoManager, ResourceAddr, ResourceManager};
4use crate::server::{AsyncSignal, Config, State, SyncSignal};
5use crate::util::spin_sleeper;
6use eframe::egui::Ui;
7use eyre::Result;
8use serde::{Deserialize, Serialize};
9use std::collections::BTreeSet;
10use std::sync::{Arc, Mutex};
11use std::thread;
12use std::time::Duration;
13
14#[derive(Debug, Deserialize, Serialize)]
15pub struct Delayed(f32, Box<dyn Action>);
16
17stateful!(Delayed {
18 duration: Duration,
19 wait_over: Arc<Mutex<bool>>,
20 has_begun: bool,
21 inner: Box<dyn StatefulAction>,
22});
23
24impl Action for Delayed {
25 #[inline]
26 fn in_signals(&self) -> BTreeSet<SignalId> {
27 self.1.in_signals()
28 }
29
30 #[inline]
31 fn out_signals(&self) -> BTreeSet<SignalId> {
32 self.1.out_signals()
33 }
34
35 #[inline(always)]
36 fn resources(&self, config: &Config) -> Vec<ResourceAddr> {
37 self.1.resources(config)
38 }
39
40 fn stateful(
41 &self,
42 io: &IoManager,
43 res: &ResourceManager,
44 config: &Config,
45 sync_writer: &QWriter<SyncSignal>,
46 async_writer: &QWriter<AsyncSignal>,
47 ) -> Result<Box<dyn StatefulAction>> {
48 let inner = self
49 .1
50 .stateful(io, res, config, sync_writer, async_writer)?;
51
52 Ok(Box::new(StatefulDelayed {
53 done: inner.is_over()?,
54 duration: Duration::from_secs_f32(self.0),
55 wait_over: Arc::new(Mutex::new(false)),
56 has_begun: false,
57 inner,
58 }))
59 }
60}
61
62impl StatefulAction for StatefulDelayed {
63 impl_stateful!();
64
65 fn props(&self) -> Props {
66 if self.has_begun {
67 self.inner.props()
68 } else {
69 DEFAULT.into()
70 }
71 }
72
73 fn start(
74 &mut self,
75 sync_writer: &mut QWriter<SyncSignal>,
76 _async_writer: &mut QWriter<AsyncSignal>,
77 _state: &State,
78 ) -> Result<Signal> {
79 if self.done {
80 sync_writer.push(SyncSignal::UpdateGraph);
81 } else {
82 let wait_over = self.wait_over.clone();
83 let dur = self.duration;
84 let mut sync_writer = sync_writer.clone();
85 thread::spawn(move || {
86 spin_sleeper().sleep(dur);
87 *wait_over.lock().unwrap() = true;
88 sync_writer.push(SyncSignal::UpdateGraph);
89 });
90 }
91 Ok(Signal::none())
92 }
93
94 fn update(
95 &mut self,
96 signal: &ActionSignal,
97 sync_writer: &mut QWriter<SyncSignal>,
98 async_writer: &mut QWriter<AsyncSignal>,
99 state: &State,
100 ) -> Result<Signal> {
101 if *self.wait_over.lock().unwrap() {
102 let news = if !self.has_begun {
103 self.has_begun = true;
104 self.inner.start(sync_writer, async_writer, state)?
105 } else {
106 self.inner
107 .update(signal, sync_writer, async_writer, state)?
108 };
109
110 if self.inner.is_over()? {
111 self.done = true;
112 }
113 Ok(news)
114 } else {
115 Ok(Signal::none())
116 }
117 }
118
119 fn show(
120 &mut self,
121 ui: &mut Ui,
122 sync_writer: &mut QWriter<SyncSignal>,
123 async_writer: &mut QWriter<AsyncSignal>,
124 state: &State,
125 ) -> Result<()> {
126 if self.has_begun {
127 self.inner.show(ui, sync_writer, async_writer, state)
128 } else {
129 Ok(())
130 }
131 }
132
133 fn stop(
134 &mut self,
135 sync_writer: &mut QWriter<SyncSignal>,
136 async_writer: &mut QWriter<AsyncSignal>,
137 state: &State,
138 ) -> Result<Signal> {
139 if *self.wait_over.lock().unwrap() {
140 self.inner.stop(sync_writer, async_writer, state)
141 } else {
142 Ok(Signal::none())
143 }
144 }
145}