mewo_ecs/run.rs
1use super::*;
2use std::thread;
3
4/// Block the current thread, driving the `galaxy` with `systems`.
5pub fn run_single(mut galaxy: Galaxy, systems: &[fn(&Galaxy)]) {
6 loop {
7 systems.iter().for_each(|sys| sys(&galaxy));
8 if galaxy.update().is_none() {
9 return;
10 }
11 }
12}
13
14/// Spawn a new thread and drive `galaxy` with `systems`.
15/// `pre_update` and `post_update` are called before updating and after updating respectively.
16/// `pre_update` and `post_update` don't lock `galaxy`, so they don't impose side effects on other
17/// threads.
18/// In other words, you can safely block or wait in these functions.
19///
20/// Compared to [`self::run_spawn`], this function read locks `galaxy` once meaning that other
21/// threads cannot update until all systems have completed.
22pub fn run_spawn_locked(
23 galaxy: Arc<RwLock<Galaxy>>,
24 systems: &[fn(&Galaxy)],
25 pre_update: fn(&Arc<RwLock<Galaxy>>),
26 post_update: fn(&Arc<RwLock<Galaxy>>),
27) -> thread::JoinHandle<()> {
28 let systems = systems.to_owned();
29 thread::spawn(move || loop {
30 pre_update(&galaxy);
31
32 {
33 let galaxy = galaxy.read();
34 systems.iter().for_each(|sys| sys(&galaxy));
35 }
36 {
37 let mut galaxy = galaxy.write();
38 if galaxy.update().is_none() {
39 return;
40 }
41 }
42
43 post_update(&galaxy);
44 })
45}
46
47/// Spawn a new thread and drive `galaxy` with `systems`.
48/// `pre_update` and `post_update` are called before updating and after updating respectively.
49/// `pre_update` and `post_update` don't lock `galaxy`, so they don't impose side effects on other
50/// threads.
51/// In other words, you can safely block or wait in these functions.
52///
53/// Compared to [`self::run_spawn_locked`], this function read locks `galaxy` on each system call.
54/// This means that other threads can update between system calls.
55pub fn run_spawn(
56 galaxy: Arc<RwLock<Galaxy>>,
57 systems: &[fn(&Galaxy)],
58 pre_update: fn(&Arc<RwLock<Galaxy>>),
59 post_update: fn(&Arc<RwLock<Galaxy>>),
60) -> thread::JoinHandle<()> {
61 let systems = systems.to_owned();
62 thread::spawn(move || loop {
63 pre_update(&galaxy);
64
65 {
66 systems.iter().for_each(|sys| {
67 let galaxy = galaxy.read();
68 sys(&galaxy)
69 });
70 }
71 {
72 let mut galaxy = galaxy.write();
73 if galaxy.update().is_none() {
74 return;
75 }
76 }
77
78 post_update(&galaxy);
79 })
80}