shadow_rs/utility/
perf_timer.rs

1use std::sync::atomic::{Ordering, compiler_fence};
2use std::time::{Duration, Instant};
3
4/// Intended as a drop-in-replacement for glib's GTimer.
5pub struct PerfTimer {
6    start_time: Option<Instant>,
7    elapsed: Duration,
8}
9
10impl PerfTimer {
11    /// Create a timer, and start it.
12    pub fn new_started() -> Self {
13        Self {
14            start_time: Some(Instant::now()),
15            elapsed: Duration::new(0, 0),
16        }
17    }
18
19    /// Create a timer, but don't start it.
20    pub fn new_stopped() -> Self {
21        Self {
22            start_time: None,
23            elapsed: Duration::new(0, 0),
24        }
25    }
26
27    /// Start the timer, which must not already be running.
28    pub fn start(&mut self) {
29        compiler_fence(Ordering::SeqCst);
30        debug_assert!(self.start_time.is_none());
31        self.start_time = Some(Instant::now());
32        compiler_fence(Ordering::SeqCst);
33    }
34
35    /// Stop the timer, which must already be running.
36    pub fn stop(&mut self) {
37        compiler_fence(Ordering::SeqCst);
38        debug_assert!(self.start_time.is_some());
39        if let Some(t) = self.start_time.take() {
40            self.elapsed += Instant::now().duration_since(t)
41        }
42        compiler_fence(Ordering::SeqCst);
43    }
44
45    /// Total time elapsed while the timer has been running.
46    pub fn elapsed(&self) -> Duration {
47        let mut e = self.elapsed;
48        if let Some(t) = self.start_time.as_ref() {
49            e += Instant::now().duration_since(*t)
50        }
51        e
52    }
53}
54
55impl Default for PerfTimer {
56    fn default() -> Self {
57        Self::new_started()
58    }
59}