use std;
use time;
#[derive(Copy, Clone)]
pub struct Fps {
fps: f64,
last_ns: u64,
high_priority: bool,
}
impl Fps {
pub fn new(fps: f64) -> Fps {
assert!(fps > 0.0, "The given frames per seconds must be greater than 0.");
Fps { fps: fps, last_ns: time::precise_time_ns(), high_priority: false }
}
pub fn high_priority(self) -> Fps {
Fps { high_priority: true, ..self }
}
#[inline]
pub fn frame_ns(&self) -> u64 { (BILLION / self.fps) as u64 }
#[inline]
pub fn get_dt_ns(&self, t: u64) -> u64 {
if t >= self.last_ns {
t - self.last_ns
} else {
use std::u64::MAX;
(MAX - self.last_ns) + t
}
}
}
const BILLION: f64 = 1_000_000_000.0;
pub type DeltaSecs = f64;
#[inline]
fn ns_to_secs(n: u64) -> f64 { n as f64 / BILLION }
impl Iterator for Fps {
type Item = DeltaSecs;
fn next(&mut self) -> Option<DeltaSecs> {
let frame_ns = self.frame_ns();
let t_ns = time::precise_time_ns();
let dt_ns = self.get_dt_ns(t_ns);
if dt_ns >= frame_ns {
self.last_ns = t_ns;
Some(ns_to_secs(dt_ns))
}
else {
if !self.high_priority {
let ms = ((frame_ns - dt_ns) as u64) / 1_000_000;
std::thread::sleep(std::time::Duration::from_millis(ms));
}
let mut t_ns = time::precise_time_ns();
let mut dt_ns = self.get_dt_ns(t_ns);
while dt_ns < frame_ns {
t_ns = time::precise_time_ns();
dt_ns = self.get_dt_ns(t_ns);
}
self.last_ns = t_ns;
Some(ns_to_secs(dt_ns))
}
}
}