1use crate::{Machine, Terminated};
4
5#[derive(Clone, Copy, Debug, PartialEq, Eq)]
7pub enum HierarchicalDispatch {
8 Child,
10 ChildTerminated,
12 Parent,
14 Unhandled,
16}
17
18pub struct Hierarchical<P, C> {
24 parent: P,
25 child: C,
26 child_active: bool,
27}
28
29impl<P, C> Hierarchical<P, C> {
30 pub const fn new(parent: P, child: C) -> Self {
32 Self {
33 parent,
34 child,
35 child_active: false,
36 }
37 }
38
39 pub const fn new_active(parent: P, child: C) -> Self {
41 Self {
42 parent,
43 child,
44 child_active: true,
45 }
46 }
47
48 pub fn activate_child(&mut self) {
50 self.child_active = true;
51 }
52
53 pub fn deactivate_child(&mut self) {
55 self.child_active = false;
56 }
57
58 pub fn reset_child(&mut self, child: C) {
60 self.child = child;
61 self.child_active = true;
62 }
63
64 pub const fn child_is_active(&self) -> bool {
66 self.child_active
67 }
68
69 pub fn parent(&self) -> &P {
71 &self.parent
72 }
73
74 pub fn parent_mut(&mut self) -> &mut P {
76 &mut self.parent
77 }
78
79 pub fn child(&self) -> &C {
81 &self.child
82 }
83
84 pub fn child_mut(&mut self) -> &mut C {
86 &mut self.child
87 }
88
89 pub fn process_event<E, FC, FP>(
92 &mut self,
93 event: E,
94 mut child_dispatch: FC,
95 mut parent_dispatch: FP,
96 ) -> HierarchicalDispatch
97 where
98 E: Clone,
99 C: Terminated,
100 FC: FnMut(&mut C, E) -> bool,
101 FP: FnMut(&mut P, E) -> bool,
102 {
103 if self.child_active && child_dispatch(&mut self.child, event.clone()) {
104 return if self.child.is_terminated() {
105 HierarchicalDispatch::ChildTerminated
106 } else {
107 HierarchicalDispatch::Child
108 };
109 }
110
111 if parent_dispatch(&mut self.parent, event) {
112 HierarchicalDispatch::Parent
113 } else {
114 HierarchicalDispatch::Unhandled
115 }
116 }
117
118 pub fn process_event_with_completion<E, FC, FP, FT>(
124 &mut self,
125 event: E,
126 mut child_dispatch: FC,
127 mut parent_dispatch: FP,
128 mut child_completion: FT,
129 ) -> HierarchicalDispatch
130 where
131 E: Clone,
132 C: Terminated,
133 FC: FnMut(&mut C, E) -> bool,
134 FP: FnMut(&mut P, E) -> bool,
135 FT: FnMut(&mut P) -> bool,
136 {
137 if self.child_active && child_dispatch(&mut self.child, event.clone()) {
138 if self.child.is_terminated() {
139 if child_completion(&mut self.parent) {
140 self.child_active = false;
141 return HierarchicalDispatch::Parent;
142 }
143 return HierarchicalDispatch::ChildTerminated;
144 }
145 return HierarchicalDispatch::Child;
146 }
147
148 if parent_dispatch(&mut self.parent, event) {
149 HierarchicalDispatch::Parent
150 } else {
151 HierarchicalDispatch::Unhandled
152 }
153 }
154}
155
156#[derive(Clone, Copy, Debug, PartialEq, Eq)]
158pub struct QueueFull;
159
160pub struct EventQueue<E, const N: usize> {
162 events: [Option<E>; N],
163 head: usize,
164 len: usize,
165}
166
167impl<E, const N: usize> EventQueue<E, N> {
168 pub const fn new() -> Self {
170 Self {
171 events: [const { None }; N],
172 head: 0,
173 len: 0,
174 }
175 }
176
177 pub const fn len(&self) -> usize {
179 self.len
180 }
181
182 pub const fn is_empty(&self) -> bool {
184 self.len == 0
185 }
186
187 pub fn defer(&mut self, event: E) -> Result<(), QueueFull> {
189 if self.len == N || N == 0 {
190 return Err(QueueFull);
191 }
192 let tail = (self.head + self.len) % N;
193 self.events[tail] = Some(event);
194 self.len += 1;
195 Ok(())
196 }
197
198 pub fn process(&mut self, event: E) -> Result<(), QueueFull> {
200 if self.len == N || N == 0 {
201 return Err(QueueFull);
202 }
203 self.head = (self.head + N - 1) % N;
204 self.events[self.head] = Some(event);
205 self.len += 1;
206 Ok(())
207 }
208
209 pub fn pop(&mut self) -> Option<E> {
211 if self.len == 0 {
212 return None;
213 }
214 let event = self.events[self.head].take();
215 self.head = (self.head + 1) % N;
216 self.len -= 1;
217 event
218 }
219
220 pub fn clear(&mut self) {
222 while self.pop().is_some() {}
223 }
224}
225
226impl<E, const N: usize> Default for EventQueue<E, N> {
227 fn default() -> Self {
228 Self::new()
229 }
230}
231
232#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
234pub struct DispatchStatus {
235 pub handled: bool,
237 pub transitioned: bool,
239}
240
241#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
243pub struct DispatchSummary {
244 pub dispatched: usize,
246 pub handled: usize,
248 pub transitioned: usize,
250}
251
252impl DispatchSummary {
253 fn record(&mut self, status: DispatchStatus) {
254 self.dispatched += 1;
255 self.handled += usize::from(status.handled);
256 self.transitioned += usize::from(status.transitioned);
257 }
258}
259
260pub struct EventQueues<E, const DEFERRED: usize, const PROCESSED: usize> {
262 deferred: EventQueue<E, DEFERRED>,
263 processed: EventQueue<E, PROCESSED>,
264}
265
266impl<E, const DEFERRED: usize, const PROCESSED: usize> EventQueues<E, DEFERRED, PROCESSED> {
267 pub const fn new() -> Self {
269 Self {
270 deferred: EventQueue::new(),
271 processed: EventQueue::new(),
272 }
273 }
274
275 pub fn defer(&mut self, event: E) -> Result<(), QueueFull> {
277 self.deferred.defer(event)
278 }
279
280 pub fn process(&mut self, event: E) -> Result<(), QueueFull> {
282 self.processed.defer(event)
283 }
284
285 pub const fn deferred_len(&self) -> usize {
287 self.deferred.len()
288 }
289
290 pub const fn processed_len(&self) -> usize {
292 self.processed.len()
293 }
294
295 pub fn dispatch<M, F>(&mut self, machine: &mut M, event: E, mut dispatch: F) -> DispatchSummary
298 where
299 F: FnMut(&mut M, &mut Self, E) -> DispatchStatus,
300 {
301 let mut summary = DispatchSummary::default();
302 let initial = dispatch(machine, self, event);
303 summary.record(initial);
304 self.drain_processed(machine, &mut dispatch, &mut summary);
305
306 if summary.transitioned > 0 {
307 let retries = self.deferred.len();
308 for _ in 0..retries {
309 if let Some(event) = self.deferred.pop() {
310 let status = dispatch(machine, self, event);
311 summary.record(status);
312 self.drain_processed(machine, &mut dispatch, &mut summary);
313 }
314 }
315 }
316
317 summary
318 }
319
320 fn drain_processed<M, F>(
321 &mut self,
322 machine: &mut M,
323 dispatch: &mut F,
324 summary: &mut DispatchSummary,
325 ) where
326 F: FnMut(&mut M, &mut Self, E) -> DispatchStatus,
327 {
328 while let Some(event) = self.processed.pop() {
329 summary.record(dispatch(machine, self, event));
330 }
331 }
332}
333
334impl<E, const DEFERRED: usize, const PROCESSED: usize> Default
335 for EventQueues<E, DEFERRED, PROCESSED>
336{
337 fn default() -> Self {
338 Self::new()
339 }
340}
341
342pub struct DispatchTable<'a, M, Raw, R> {
347 machine: &'a mut M,
348 first_id: usize,
349 handlers: &'a [fn(&mut M, &Raw) -> R],
350}
351
352impl<'a, M, Raw, R> DispatchTable<'a, M, Raw, R> {
353 pub const fn new(
355 machine: &'a mut M,
356 first_id: usize,
357 handlers: &'a [fn(&mut M, &Raw) -> R],
358 ) -> Self {
359 Self {
360 machine,
361 first_id,
362 handlers,
363 }
364 }
365
366 #[inline]
370 pub fn dispatch(&mut self, raw: &Raw, id: usize) -> Option<R> {
371 let index = id.checked_sub(self.first_id)?;
372 let handler = *self.handlers.get(index)?;
373 Some(handler(self.machine, raw))
374 }
375
376 pub fn machine(&self) -> &M {
378 self.machine
379 }
380
381 pub fn machine_mut(&mut self) -> &mut M {
383 self.machine
384 }
385}
386
387#[derive(Clone, Debug, PartialEq, Eq)]
389pub struct IndexedEvent<E> {
390 pub index: usize,
392 pub event: E,
394}
395
396pub const fn with_id<E>(index: usize, event: E) -> IndexedEvent<E> {
398 IndexedEvent { index, event }
399}
400
401pub struct SmPool<S> {
407 storage: S,
408}
409
410pub struct OrthogonalRegions<S> {
415 regions: S,
416}
417
418impl<S> OrthogonalRegions<S> {
419 pub const fn new(regions: S) -> Self {
421 Self { regions }
422 }
423
424 pub fn regions(&self) -> &S {
426 &self.regions
427 }
428
429 pub fn regions_mut(&mut self) -> &mut S {
431 &mut self.regions
432 }
433
434 pub fn process_event<M, E>(&mut self, event: E) -> usize
437 where
438 S: AsMut<[M]>,
439 M: Machine<E>,
440 E: Clone,
441 {
442 self.regions.as_mut().iter_mut().fold(0, |handled, region| {
443 handled + usize::from(Machine::process_event(region, event.clone()))
444 })
445 }
446}
447
448impl<S> SmPool<S> {
449 pub const fn new(storage: S) -> Self {
451 Self { storage }
452 }
453
454 pub fn storage(&self) -> &S {
456 &self.storage
457 }
458
459 pub fn storage_mut(&mut self) -> &mut S {
461 &mut self.storage
462 }
463
464 pub fn reset<M, F>(&mut self, mut initialize: F)
466 where
467 S: AsMut<[M]>,
468 F: FnMut(usize) -> M,
469 {
470 for (index, machine) in self.storage.as_mut().iter_mut().enumerate() {
471 *machine = initialize(index);
472 }
473 }
474
475 #[inline]
477 pub fn process_indexed<M, E, R, F>(&mut self, index: usize, event: E, dispatch: F) -> Option<R>
478 where
479 S: AsMut<[M]>,
480 F: FnOnce(&mut M, E) -> R,
481 {
482 self.storage
483 .as_mut()
484 .get_mut(index)
485 .map(|machine| dispatch(machine, event))
486 }
487
488 pub fn process_indexed_batch<M, E, I, F>(
492 &mut self,
493 indices: I,
494 event: E,
495 mut dispatch: F,
496 ) -> usize
497 where
498 S: AsMut<[M]>,
499 E: Clone,
500 I: IntoIterator<Item = usize>,
501 F: FnMut(&mut M, E),
502 {
503 let machines = self.storage.as_mut();
504 let mut handled = 0;
505 for index in indices {
506 if let Some(machine) = machines.get_mut(index) {
507 dispatch(machine, event.clone());
508 handled += 1;
509 }
510 }
511 handled
512 }
513
514 pub fn process_event_batch<M, E, I, F>(&mut self, events: I, mut dispatch: F) -> usize
518 where
519 S: AsMut<[M]>,
520 I: IntoIterator<Item = IndexedEvent<E>>,
521 F: FnMut(&mut M, E),
522 {
523 let machines = self.storage.as_mut();
524 let mut handled = 0;
525 for IndexedEvent { index, event } in events {
526 if let Some(machine) = machines.get_mut(index) {
527 dispatch(machine, event);
528 handled += 1;
529 }
530 }
531 handled
532 }
533}