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}