1use std;
9use time;
10
11#[derive(Copy, Clone)]
14pub struct Fps {
15 fps: f64,
16 last_ns: u64,
17 high_priority: bool,
18}
19
20impl Fps {
21
22 pub fn new(fps: f64) -> Fps {
24 assert!(fps > 0.0, "The given frames per seconds must be greater than 0.");
25 Fps { fps: fps, last_ns: time::precise_time_ns(), high_priority: false }
26 }
27
28 pub fn high_priority(self) -> Fps {
31 Fps { high_priority: true, ..self }
32 }
33
34 #[inline]
36 pub fn frame_ns(&self) -> u64 { (BILLION / self.fps) as u64 }
37
38 #[inline]
40 pub fn get_dt_ns(&self, t: u64) -> u64 {
41 if t >= self.last_ns {
42 t - self.last_ns
43 } else {
44 use std::u64::MAX;
45 (MAX - self.last_ns) + t
46 }
47 }
48
49}
50
51const BILLION: f64 = 1_000_000_000.0;
52pub type DeltaSecs = f64;
53
54#[inline]
56fn ns_to_secs(n: u64) -> f64 { n as f64 / BILLION }
57
58impl Iterator for Fps {
59 type Item = DeltaSecs;
60 fn next(&mut self) -> Option<DeltaSecs> {
61 let frame_ns = self.frame_ns();
62 let t_ns = time::precise_time_ns();
63 let dt_ns = self.get_dt_ns(t_ns);
64 if dt_ns >= frame_ns {
65 self.last_ns = t_ns;
66 Some(ns_to_secs(dt_ns))
67 }
68 else {
69 if !self.high_priority {
70 let ms = ((frame_ns - dt_ns) as u64) / 1_000_000;
72 std::thread::sleep(std::time::Duration::from_millis(ms));
73 }
74 let mut t_ns = time::precise_time_ns();
75 let mut dt_ns = self.get_dt_ns(t_ns);
76 while dt_ns < frame_ns {
77 t_ns = time::precise_time_ns();
78 dt_ns = self.get_dt_ns(t_ns);
79 }
80 self.last_ns = t_ns;
81 Some(ns_to_secs(dt_ns))
82 }
83 }
84}
85