coarsetime/
updater.rs

1use std::io;
2use std::sync::atomic::{AtomicBool, Ordering};
3use std::sync::Arc;
4use std::thread;
5use std::time;
6
7use super::clock::*;
8use super::instant::*;
9
10/// A service to periodically call `Instant::update()`
11#[derive(Debug)]
12pub struct Updater {
13    period: time::Duration,
14    running: Arc<AtomicBool>,
15    th: Option<thread::JoinHandle<()>>,
16}
17
18impl Updater {
19    /// Spawns a background task to call `Instant::update()` periodically
20    pub fn start(mut self) -> Result<Self, io::Error> {
21        let period = self.period;
22        let running = self.running.clone();
23        running.store(true, Ordering::Relaxed);
24        let th: thread::JoinHandle<()> = thread::Builder::new()
25            .name("coarsetime".to_string())
26            .spawn(move || {
27                while running.load(Ordering::Relaxed) {
28                    thread::sleep(period);
29                    Instant::update();
30                    Clock::update();
31                }
32            })?;
33        self.th = Some(th);
34        Instant::update();
35        Clock::update();
36        Ok(self)
37    }
38
39    /// Stops the periodic updates
40    pub fn stop(mut self) -> Result<(), io::Error> {
41        self.running.store(false, Ordering::Relaxed);
42        self.th
43            .take()
44            .expect("updater is not running")
45            .join()
46            .map_err(|_| {
47                io::Error::new(io::ErrorKind::Other, "failed to properly stop the updater")
48            })
49    }
50
51    /// Creates a new `Updater` with the specified update period, in
52    /// milliseconds.
53    pub fn new(period_millis: u64) -> Updater {
54        Updater {
55            period: time::Duration::from_millis(period_millis),
56            running: Arc::new(AtomicBool::new(false)),
57            th: None,
58        }
59    }
60}