1use crate::runtime::action::Tick;
2use crate::runtime::args::{RtArgs, RtValue};
3use crate::runtime::blackboard::{BBRef, BlackBoard};
4use crate::runtime::env::RtEnvRef;
5use crate::runtime::forester::flow::REASON;
6use crate::runtime::rtree::rnode::RNodeId;
7use crate::runtime::trimmer::{TrimmingQueue, TrimmingQueueRef};
8use crate::runtime::{RtOk, RtResult, RuntimeError, TickResult};
9use crate::tracer::Event::NewState;
10use crate::tracer::{Event, Tracer};
11use std::collections::{HashMap, VecDeque};
12use std::fmt::{Display, Formatter};
13use std::sync::Arc;
14use std::sync::Mutex;
15
16use super::rtree::rnode::RNode;
17
18pub type Timestamp = usize;
19pub type TracerRef = Arc<Mutex<Tracer>>;
20
21pub struct TreeRemoteContextRef {
29 pub curr_ts: Timestamp,
30 pub port: u16,
31 pub env: RtEnvRef,
32}
33
34impl TreeRemoteContextRef {
35 pub fn new(curr_ts: Timestamp, port: u16, env: RtEnvRef) -> Self {
36 Self { curr_ts, port, env }
37 }
38}
39
40#[derive(Clone)]
44pub struct TreeContextRef {
45 bb: BBRef,
46 tracer: TracerRef,
47 curr_ts: Timestamp,
48 _trimmer: TrimmingQueueRef,
49 env: RtEnvRef,
50}
51
52impl From<&mut TreeContext> for TreeContextRef {
53 fn from(value: &mut TreeContext) -> Self {
54 TreeContextRef::from_ctx(value, Default::default())
55 }
56}
57
58impl TreeContextRef {
59 pub fn from_ctx(ctx: &TreeContext, trimmer: Arc<Mutex<TrimmingQueue>>) -> Self {
60 TreeContextRef::new(
61 ctx.bb.clone(),
62 ctx.tracer.clone(),
63 ctx.curr_ts,
64 trimmer,
65 ctx.rt_env.clone(),
66 )
67 }
68 pub fn tracer(&self) -> TracerRef {
70 self.tracer.clone()
71 }
72 pub fn trace(&self, ev: String) -> RtOk {
74 self.tracer.lock()?.trace(self.curr_ts, Event::Custom(ev))
75 }
76 pub fn trace_ev(&self, ev: Event) -> RtOk {
77 self.tracer.lock()?.trace(self.curr_ts, ev)
78 }
79 pub fn bb(&self) -> BBRef {
81 self.bb.clone()
82 }
83
84 pub fn env(&self) -> RtEnvRef {
85 self.env.clone()
86 }
87 pub fn current_tick(&self) -> Timestamp {
89 self.curr_ts
90 }
91 pub fn new(
92 bb: Arc<Mutex<BlackBoard>>,
93 tracer: Arc<Mutex<Tracer>>,
94 curr_ts: Timestamp,
95 _trimmer: Arc<Mutex<TrimmingQueue>>,
96 env: RtEnvRef,
97 ) -> Self {
98 Self {
99 bb,
100 tracer,
101 curr_ts,
102 _trimmer,
103 env,
104 }
105 }
106}
107
108pub struct TreeContext {
111 bb: BBRef,
113 tracer: TracerRef,
115
116 stack: VecDeque<RNodeId>,
118
119 state: HashMap<RNodeId, RNodeState>,
121
122 ts_map: HashMap<RNodeId, Timestamp>,
124
125 curr_ts: Timestamp,
127
128 tick_limit: Timestamp,
130
131 rt_env: RtEnvRef,
133}
134
135impl TreeContext {
136 pub fn state(&self) -> &HashMap<RNodeId, RNodeState> {
137 &self.state
138 }
139
140 pub fn bb(&mut self) -> Arc<Mutex<BlackBoard>> {
142 self.bb.clone()
143 }
144 pub fn tracer(&mut self) -> Arc<Mutex<Tracer>> {
145 self.tracer.clone()
146 }
147 pub fn new(bb: BBRef, tracer: TracerRef, tick_limit: Timestamp, rt_env: RtEnvRef) -> Self {
148 Self {
149 bb,
150 tracer,
151 stack: Default::default(),
152 state: Default::default(),
153 ts_map: Default::default(),
154 curr_ts: 1,
155 tick_limit,
156 rt_env,
157 }
158 }
159}
160
161impl TreeContext {
162 pub fn trace(&mut self, ev: Event) -> RtOk {
165 self.tracer.lock()?.trace(self.curr_ts, ev)
166 }
167
168 pub(crate) fn next_tick(&mut self) -> RtOk {
169 self.curr_ts += 1;
170 self.trace(Event::NextTick)?;
171 debug!(target:"root", "tick up the flow to:{}",self.curr_ts);
172 if self.tick_limit != 0 && self.curr_ts >= self.tick_limit {
173 Err(RuntimeError::Stopped(format!(
174 "the limit of ticks are exceeded on {}",
175 self.curr_ts
176 )))
177 } else {
178 Ok(())
179 }
180 }
181
182 pub(crate) fn root_state(&self, root: RNodeId) -> Tick {
183 self.state
184 .get(&root)
185 .ok_or(RuntimeError::uex(format!("the root node {root} is absent")))
186 .and_then(RNodeState::to_tick_result)
187 }
188
189 pub(crate) fn is_curr_ts(&self, id: &RNodeId) -> bool {
190 self.ts_map
191 .get(id)
192 .map(|e| *e == self.curr_ts)
193 .unwrap_or(false)
194 }
195 pub fn curr_ts(&self) -> Timestamp {
196 self.curr_ts
197 }
198
199 pub(crate) fn push(&mut self, id: RNodeId) -> RtOk {
200 self.tracer.lock()?.right();
201 self.stack.push_back(id);
202 Ok(())
203 }
204 pub(crate) fn pop(&mut self) -> RtResult<Option<RNodeId>> {
205 let pop_node = self.stack.pop_back();
206 self.tracer.lock()?.left();
207 Ok(pop_node)
208 }
209 pub(crate) fn peek(&self) -> RtResult<Option<&RNodeId>> {
210 if self.stack.is_empty() {
211 Ok(None)
212 } else {
213 Ok(self.stack.back())
214 }
215 }
216
217 pub(crate) fn force_to_halting_state(&mut self, id: RNodeId) -> RtResult<Option<RNodeState>> {
218 self.ts_map.insert(id, self.curr_ts);
219 let new_state = RNodeState::Halting(self.state_last_set(&id).args());
220
221 self.tracer.lock()?.right();
223 self.trace(NewState(id, new_state.clone()))?;
224 self.tracer.lock()?.left();
225
226 Ok(self.state.insert(id, new_state))
227 }
228 pub(crate) fn new_state(
229 &mut self,
230 id: RNodeId,
231 state: RNodeState,
232 ) -> RtResult<Option<RNodeState>> {
233 self.ts_map.insert(id, self.curr_ts);
234 self.trace(NewState(id, state.clone()))?;
235 Ok(self.state.insert(id, state))
236 }
237 pub(crate) fn state_last_set(&self, id: &RNodeId) -> RNodeState {
238 self.state
239 .get(id)
240 .cloned()
241 .unwrap_or(RNodeState::Ready(RtArgs::default()))
242 }
243 pub(crate) fn state_in_ts(&self, id: &RNodeId) -> RNodeState {
244 let actual_state = self.state_last_set(id);
245 if self.is_curr_ts(&id) {
246 actual_state
247 } else {
248 RNodeState::Ready(actual_state.args())
249 }
250 }
251}
252
253#[derive(Clone, Debug)]
256pub enum RNodeState {
257 Ready(RtArgs),
258 Running(RtArgs),
259 Success(RtArgs),
260 Failure(RtArgs),
261 Halting(RtArgs),
262}
263
264impl Display for RNodeState {
265 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
266 match self {
267 RNodeState::Ready(args) => {
268 f.write_str(format!("Ready({})", args).as_str())?;
269 }
270 RNodeState::Running(args) => {
271 f.write_str(format!("Running({})", args).as_str())?;
272 }
273 RNodeState::Success(args) => {
274 f.write_str(format!("Success({})", args).as_str())?;
275 }
276 RNodeState::Failure(args) => {
277 f.write_str(format!("Failure({})", args).as_str())?;
278 }
279 RNodeState::Halting(args) => {
280 f.write_str(format!("Halting({})", args).as_str())?;
281 }
282 }
283 Ok(())
284 }
285}
286
287impl RNodeState {
288 pub fn from(tick_args: RtArgs, res: TickResult) -> RNodeState {
289 match res {
290 TickResult::Success => RNodeState::Success(tick_args),
291 TickResult::Failure(v) => RNodeState::Failure(tick_args.with(REASON, RtValue::str(v))),
292 TickResult::Running => RNodeState::Running(tick_args),
293 }
294 }
295 pub fn to_tick_result(&self) -> RtResult<TickResult> {
296 match &self {
297 RNodeState::Ready(_) => Err(RuntimeError::uex(
298 "the ready is the unexpected state for ".to_string(),
299 )),
300 RNodeState::Running(_) | RNodeState::Halting(_) => Ok(TickResult::running()),
301 RNodeState::Success(_) => Ok(TickResult::success()),
302 RNodeState::Failure(args) => {
303 let reason = args
304 .find(REASON.to_string())
305 .and_then(RtValue::as_string)
306 .unwrap_or_default();
307
308 Ok(TickResult::Failure(reason))
309 }
310 }
311 }
312
313 pub fn is_running(&self) -> bool {
314 matches!(self, RNodeState::Running { .. })
315 }
316 pub fn is_ready(&self) -> bool {
317 matches!(self, RNodeState::Ready(_))
318 }
319 pub fn is_finished(&self) -> bool {
320 matches!(self, RNodeState::Success(_) | RNodeState::Failure(_))
321 }
322
323 pub fn args(&self) -> RtArgs {
324 match self {
325 RNodeState::Ready(tick_args)
326 | RNodeState::Running(tick_args)
327 | RNodeState::Failure(tick_args)
328 | RNodeState::Success(tick_args)
329 | RNodeState::Halting(tick_args) => tick_args.clone(),
330 }
331 }
332}