xand-utils 1.0.0

A junk drawer of shared Rust utilities.
Documentation
use std::{thread::JoinHandle, time::Duration};

/// Use to spawn a thread that will be restarted automatically (after a one second delay) if it
/// panics. Primarily useful for running an infinite-lifetime job (like a webserver) in another
/// thread. If the passed function exits cleanly, it is not restarted.
pub fn spawn_immortal<F, T>(f: F) -> JoinHandle<T>
where
    F: FnOnce() -> T + Send + Clone + 'static,
    T: Send + 'static,
{
    std::thread::spawn(move || loop {
        let handle = std::thread::spawn(f.clone());
        match handle.join() {
            Err(_) => (),
            Ok(h) => {
                return h;
            }
        }
        std::thread::sleep(Duration::from_secs(1));
    })
}

#[cfg(test)]
mod test {
    use super::*;
    use std::sync::atomic::{AtomicU8, Ordering};

    static COUNTER: AtomicU8 = AtomicU8::new(0);

    #[test]
    fn test_can_restart() {
        // If you come here confused from test output, yes, this test intentionally spews panics.
        let jh = spawn_immortal(|| {
            let v = COUNTER.fetch_add(1, Ordering::SeqCst);
            if v < 2 {
                panic!("Ahhhh!");
            }
        });
        jh.join().unwrap();
    }
}