1use std::cell::RefCell;
4use std::future::Future;
5use std::rc::Rc;
6use std::time::Duration;
7
8use gwr_track::entity::{Entity, toplevel};
9use gwr_track::tracker::stdout_tracker;
10use gwr_track::{Tracker, trace};
11
12use crate::executor::{self, Executor, ExecutorSnapshot, ExecutorStats, Spawner};
13use crate::time::clock::Clock;
14use crate::types::{Component, SimResult};
15
16const DEFAULT_CLOCK_MHZ: f64 = 1000.0;
18
19pub struct Registry {
26 entity: Rc<Entity>,
27 components: RefCell<Vec<Component>>,
28}
29
30impl Registry {
31 fn new(parent: &Rc<Entity>) -> Self {
32 Self {
33 entity: Rc::new(Entity::new(parent, "registry")),
34 components: RefCell::new(Vec::new()),
35 }
36 }
37
38 pub fn spawn_components(&self, spawner: &Spawner) {
39 let mut guard = self.components.borrow_mut();
40
41 trace!(self.entity ; "Spawning {} components", guard.len());
42
43 for component in guard.drain(..) {
44 spawner.spawn(async move { component.run().await });
45 }
46 }
47
48 pub fn register(&self, component: Component) {
49 let mut guard = self.components.borrow_mut();
50 guard.push(component);
51 }
52}
53
54pub struct Engine {
67 pub executor: Executor,
68 spawner: Spawner,
69 toplevel: Rc<Entity>,
70 tracker: Tracker,
71 registry: Registry,
72}
73
74impl Engine {
75 pub fn new(tracker: &Tracker) -> Self {
77 let toplevel = toplevel(tracker, "top");
78 let (executor, spawner) = executor::new_executor_and_spawner(&toplevel);
79 let registry = Registry::new(&toplevel);
80 Self {
81 executor,
82 spawner,
83 toplevel,
84 tracker: tracker.clone(),
85 registry,
86 }
87 }
88
89 pub fn register(&self, component: Component) {
95 self.registry.register(component);
96 }
97
98 pub fn run(&mut self) -> SimResult {
99 self.registry.spawn_components(&self.spawner);
100 self.executor.run()
101 }
102
103 pub fn run_with_executor_observer(
109 &mut self,
110 interval: Duration,
111 observer: impl FnMut(ExecutorSnapshot) -> SimResult,
112 ) -> SimResult {
113 self.registry.spawn_components(&self.spawner);
114 self.executor.run_with_observer(interval, observer)
115 }
116
117 #[must_use]
118 pub fn spawner(&self) -> Spawner {
119 self.spawner.clone()
120 }
121
122 pub fn spawn(&self, future: impl Future<Output = SimResult> + 'static) {
123 self.spawner.spawn(future);
124 }
125
126 pub fn set_randomize_task_order(&self, randomize: bool) {
127 self.executor.set_randomize_task_order(randomize);
128 }
129
130 pub fn set_task_order_seed(&self, seed: u64) {
131 self.executor.set_task_order_seed(seed);
132 }
133
134 #[must_use]
135 pub fn default_clock(&mut self) -> Clock {
136 self.executor.get_clock(DEFAULT_CLOCK_MHZ)
137 }
138
139 #[must_use]
140 pub fn clock_hz(&mut self, freq_hz: f64) -> Clock {
141 self.executor.get_clock(freq_hz / 1_000_000.0)
142 }
143
144 #[must_use]
145 pub fn clock_khz(&mut self, freq_khz: f64) -> Clock {
146 self.executor.get_clock(freq_khz / 1000.0)
147 }
148
149 #[must_use]
150 pub fn clock_mhz(&mut self, freq_mhz: f64) -> Clock {
151 self.executor.get_clock(freq_mhz)
152 }
153
154 #[must_use]
155 pub fn clock_ghz(&mut self, freq_ghz: f64) -> Clock {
156 self.executor.get_clock(freq_ghz * 1000.0)
157 }
158
159 #[must_use]
160 pub fn time_now_ns(&self) -> f64 {
161 self.executor.time_now_ns()
162 }
163
164 #[must_use]
166 pub fn executor_stats(&self) -> ExecutorStats {
167 self.executor.stats()
168 }
169
170 #[must_use]
171 pub fn top(&self) -> &Rc<Entity> {
172 &self.toplevel
173 }
174
175 #[must_use]
176 pub fn tracker(&self) -> Tracker {
177 self.tracker.clone()
178 }
179}
180
181impl Default for Engine {
187 fn default() -> Self {
188 let tracker = stdout_tracker(log::Level::Info);
189 Self::new(&tracker)
190 }
191}
192
193impl Drop for Engine {
194 fn drop(&mut self) {
195 self.tracker.shutdown();
198 }
199}