metrale_scheduler/
driver.rs1pub struct TickPlan<L> {
11 pub lanes: Vec<L>,
13 pub shutdown: bool,
16}
17
18#[derive(Debug, Clone, Copy, PartialEq, Eq)]
20pub enum LaneVerdict {
21 Proceed,
23 SkipRest,
26}
27
28pub trait Core {
29 type Lane;
30 fn plan(&mut self) -> TickPlan<Self::Lane>;
32 fn execute_lane(&mut self, lane: Self::Lane) -> LaneVerdict;
34 fn end_tick(&mut self);
36 fn finish(self);
38}
39
40pub fn run<C: Core>(mut core: C) {
41 loop {
42 let plan = core.plan();
43 if plan.shutdown {
44 break;
45 }
46 let mut skip_rest = false;
47 for lane in plan.lanes {
48 if core.execute_lane(lane) == LaneVerdict::SkipRest {
49 skip_rest = true;
50 break;
51 }
52 }
53 if skip_rest {
54 continue;
55 }
56 core.end_tick();
57 }
58 core.finish();
59}
60
61#[cfg(test)]
62mod tests {
63 use super::*;
64
65 struct Scripted {
67 ticks: Vec<(Vec<LaneVerdict>, bool)>,
68 log: Vec<String>,
69 finished: std::rc::Rc<std::cell::Cell<bool>>,
70 }
71
72 impl Core for Scripted {
73 type Lane = LaneVerdict;
74 fn plan(&mut self) -> TickPlan<LaneVerdict> {
75 let (lanes, shutdown) = self.ticks.remove(0);
76 self.log
77 .push(format!("plan{}", if shutdown { " shutdown" } else { "" }));
78 TickPlan { lanes, shutdown }
79 }
80 fn execute_lane(&mut self, lane: LaneVerdict) -> LaneVerdict {
81 self.log.push(format!("lane {lane:?}"));
82 lane
83 }
84 fn end_tick(&mut self) {
85 self.log.push("end_tick".into());
86 }
87 fn finish(self) {
88 self.finished.set(true);
89 assert_eq!(
90 self.log,
91 [
92 "plan",
93 "lane Proceed",
94 "lane Proceed",
95 "end_tick",
96 "plan",
97 "lane Proceed",
98 "lane SkipRest",
99 "plan",
100 "end_tick",
101 "plan shutdown",
102 ]
103 );
104 }
105 }
106
107 #[test]
108 fn the_driver_runs_lanes_in_order_skips_the_tick_end_on_an_idle_lane_and_finishes_once() {
109 use LaneVerdict::*;
110 let finished = std::rc::Rc::new(std::cell::Cell::new(false));
111 run(Scripted {
112 ticks: vec![
113 (vec![Proceed, Proceed], false),
114 (vec![Proceed, SkipRest, Proceed], false),
116 (vec![], false),
117 (vec![Proceed], true),
118 ],
119 log: Vec::new(),
120 finished: finished.clone(),
121 });
122 assert!(finished.get());
123 }
124}