sync42/
background.rs

1//! Manage background-threads.
2
3use std::sync::atomic::{AtomicBool, Ordering};
4use std::sync::Arc;
5
6///////////////////////////////////////// BackgroundThread /////////////////////////////////////////
7
8/// A background thread.  Joins on drop, so long as there's no panic in-progress.
9pub struct BackgroundThread {
10    done: Arc<AtomicBool>,
11    thread: Option<std::thread::JoinHandle<()>>,
12}
13
14impl BackgroundThread {
15    /// Spawn a new background thread.
16    // TODO(rescrv): Make this pass in something to call rather than an Arc<AtomicBool>.
17    pub fn spawn<F: FnOnce(Arc<AtomicBool>) + Send + 'static>(f: F) -> Self {
18        let done = Arc::new(AtomicBool::new(false));
19        let done_p = Arc::clone(&done);
20        let thread = Some(std::thread::spawn(move || f(done_p)));
21        Self { done, thread }
22    }
23
24    /// Join the background thread, consuming it.
25    pub fn join(self) {
26        // Drop will join.
27    }
28}
29
30impl Drop for BackgroundThread {
31    fn drop(&mut self) {
32        self.done.store(true, Ordering::Relaxed);
33        if !std::thread::panicking() {
34            let _ = self.thread.take().unwrap().join();
35        }
36    }
37}