cog_task/action/core/
timeout.rs1use crate::action::{Action, ActionSignal, Props, StatefulAction, INFINITE};
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 Timeout(f32, Box<dyn Action>);
16
17stateful!(Timeout {
18 duration: Duration,
19 timeout_over: Arc<Mutex<bool>>,
20 inner: Box<dyn StatefulAction>,
21});
22
23impl Action for Timeout {
24 #[inline]
25 fn in_signals(&self) -> BTreeSet<SignalId> {
26 self.1.in_signals()
27 }
28
29 #[inline]
30 fn out_signals(&self) -> BTreeSet<SignalId> {
31 self.1.out_signals()
32 }
33
34 #[inline(always)]
35 fn resources(&self, config: &Config) -> Vec<ResourceAddr> {
36 self.1.resources(config)
37 }
38
39 fn stateful(
40 &self,
41 io: &IoManager,
42 res: &ResourceManager,
43 config: &Config,
44 sync_writer: &QWriter<SyncSignal>,
45 async_writer: &QWriter<AsyncSignal>,
46 ) -> Result<Box<dyn StatefulAction>> {
47 let inner = self
48 .1
49 .stateful(io, res, config, sync_writer, async_writer)?;
50
51 Ok(Box::new(StatefulTimeout {
52 done: inner.is_over()?,
53 duration: Duration::from_secs_f32(self.0),
54 timeout_over: Arc::new(Mutex::new(false)),
55 inner,
56 }))
57 }
58}
59
60impl StatefulAction for StatefulTimeout {
61 impl_stateful!();
62
63 fn props(&self) -> Props {
64 let bits = self.inner.props().bits();
65 (bits & !INFINITE).into()
66 }
67
68 fn start(
69 &mut self,
70 sync_writer: &mut QWriter<SyncSignal>,
71 async_writer: &mut QWriter<AsyncSignal>,
72 state: &State,
73 ) -> Result<Signal> {
74 if self.done {
75 sync_writer.push(SyncSignal::UpdateGraph);
76 Ok(Signal::none())
77 } else {
78 let news = self.inner.start(sync_writer, async_writer, state)?;
79
80 let dur = self.duration;
81 let timeout_over = self.timeout_over.clone();
82 let mut sync_writer = sync_writer.clone();
83 thread::spawn(move || {
84 spin_sleeper().sleep(dur);
85 *timeout_over.lock().unwrap() = true;
86 sync_writer.push(SyncSignal::UpdateGraph);
87 });
88
89 Ok(news)
90 }
91 }
92
93 fn update(
94 &mut self,
95 signal: &ActionSignal,
96 sync_writer: &mut QWriter<SyncSignal>,
97 async_writer: &mut QWriter<AsyncSignal>,
98 state: &State,
99 ) -> Result<Signal> {
100 let news = self
101 .inner
102 .update(signal, sync_writer, async_writer, state)?;
103 if self.inner.is_over()?
104 || (matches!(signal, ActionSignal::UpdateGraph) && *self.timeout_over.lock().unwrap())
105 {
106 self.done = true;
107 }
108 Ok(news)
109 }
110
111 fn show(
112 &mut self,
113 ui: &mut Ui,
114 sync_writer: &mut QWriter<SyncSignal>,
115 async_writer: &mut QWriter<AsyncSignal>,
116 state: &State,
117 ) -> Result<()> {
118 self.inner.show(ui, sync_writer, async_writer, state)
119 }
120
121 fn stop(
122 &mut self,
123 sync_writer: &mut QWriter<SyncSignal>,
124 async_writer: &mut QWriter<AsyncSignal>,
125 state: &State,
126 ) -> Result<Signal> {
127 self.inner.stop(sync_writer, async_writer, state)
128 }
129}