1use log;
7use std::sync::mpsc::{self, Receiver, Sender};
8use std::sync::{Arc, Mutex, RwLock};
9use std::time::{Duration, Instant};
10
11use crate::error::SaunterError;
12use crate::snapshot::{Snapshot, Snapshots};
13type Listener<T, E> =
14 dyn FnMut(f32, Vec<E>, TickLoopControl, Instant) -> Result<T, SaunterError> + Send;
15
16pub enum TickLoopState {
17 Running,
18 Stopped,
19 Paused,
20}
21
22pub struct TickLoopControl {
23 state: Arc<Mutex<TickLoopState>>,
24}
25
26impl TickLoopControl {
27 pub fn stop(&mut self) {
28 let mut state = self.state.lock().unwrap();
29 *state = TickLoopState::Stopped;
30 }
31
32 pub fn pause(&mut self) {
33 let mut state = self.state.lock().unwrap();
34 *state = TickLoopState::Paused;
35 }
36
37 pub fn resume(&mut self) {
38 let mut state = self.state.lock().unwrap();
39 *state = TickLoopState::Running;
40 }
41}
42
43pub struct TickLoop<S: Snapshot, E: Send> {
46 pub listener: Box<Listener<S, E>>,
47 pub tick_length: Duration,
48 reciever: Receiver<E>,
49 state: Arc<Mutex<TickLoopState>>,
50 snapshots: Arc<RwLock<Snapshots<S>>>,
51}
52
53impl<'a, S: Snapshot, E: Send> TickLoop<S, E> {
54 pub fn new<F>(
57 listener: F,
58 tps: f32,
59 reciever: Receiver<E>,
60 state: Arc<Mutex<TickLoopState>>,
61 snapshots: Arc<RwLock<Snapshots<S>>>,
62 ) -> Self
63 where
64 F: FnMut(f32, Vec<E>, TickLoopControl, Instant) -> Result<S, SaunterError> + Send + 'static,
65 {
66 let tick_length = Duration::from_secs_f32(1.0 / tps);
67 TickLoop {
68 listener: Box::new(listener),
69 tick_length,
70 reciever,
71 snapshots,
72 state,
73 }
74 }
75
76 pub fn init<F>(
78 listener: F,
79 tps: f32,
80 ) -> (
81 Self,
82 Sender<E>,
83 TickLoopControl,
84 Arc<RwLock<Snapshots<S>>>,
85 )
86 where
87 F: FnMut(f32, Vec<E>, TickLoopControl, Instant) -> Result<S, SaunterError> + Send + 'static,
88 {
89 let (event_sender, event_reciever) = mpsc::channel::<E>();
90 let snapshots = Arc::new(RwLock::new(Snapshots::new()));
91 let state = Arc::new(Mutex::new(TickLoopState::Running));
92
93 (
94 Self::new(listener, tps, event_reciever, state.clone(), snapshots.clone()),
95 event_sender,
96 TickLoopControl {
97 state: state.clone(),
98 },
99 snapshots,
100 )
101 }
102
103 pub fn start(&mut self) {
105 let mut deficit = Duration::from_secs_f32(0.0);
106
107 'a: loop {
108 let tick_time = std::time::Instant::now();
109
110 match *self.state.lock().unwrap() {
111 TickLoopState::Stopped => break 'a,
112 TickLoopState::Paused => {
113 spin_sleep::sleep(self.tick_length);
114 continue 'a;
115 }
116 TickLoopState::Running => {}
117 }
118
119 let events = self.reciever.try_iter().collect();
120
121 if let Ok(snapshot) = (self.listener)(
122 self.tick_length.as_secs_f32(),
123 events,
124 TickLoopControl {
125 state: self.state.clone(),
126 },
127 tick_time,
128 ) {
129 let mut tick_wlock = self.snapshots.write().unwrap();
130 log::debug!("lock aquired {:?}", std::time::Instant::now());
131 (*tick_wlock).update(snapshot);
132 }
134 log::debug!("lock dropped {:?}", std::time::Instant::now());
135
136 let elapsed = tick_time.elapsed();
137 if elapsed < self.tick_length {
138 let mut sleep_dur = self.tick_length - elapsed;
139 log::debug!("deficit: {:?}", deficit);
141 if deficit < sleep_dur {
142 sleep_dur -= deficit;
143 deficit = Duration::from_secs_f32(0.0);
144 } else {
145 deficit -= sleep_dur;
146 sleep_dur *= 0;
147 }
148
149 spin_sleep::sleep(self.tick_length - elapsed);
150 } else {
151 let current_tick_deficit = elapsed - self.tick_length;
152 deficit += current_tick_deficit;
153 log::debug!("tick took too long");
154 }
155
156 log::debug!("actual tick length {:?}", tick_time.elapsed());
157 }
158 }
159}