use std::{ error::Error, sync::mpsc::{channel, Sender, TryRecvError}, thread::sleep, thread::{self, JoinHandle}, time::Duration, }; pub struct ControllableThread { thread: Option>>>, sender: Sender, } impl ControllableThread { pub fn new(interval: Duration, mut f: F) -> Self where F: FnMut() -> Result<(), Box> + Send + Sync + 'static, { let (sender, receiver) = channel(); Self { thread: Some(thread::spawn(move || { loop { match receiver.try_recv() { Ok(b) => { if b { break; } } Err(err) => { if let TryRecvError::Disconnected = err { panic!("channel disconnected!"); } } } f()?; sleep(interval); } Ok(()) })), sender, } } } impl Drop for ControllableThread { fn drop(&mut self) { if let Err(err) = self.sender.send(true) { println!("mpsc send error: {}", err); } self.thread.take().map(|thread| match thread.join() { Ok(res) => { if let Err(err) = res { println!("callback error inside thread: {}", err); } } Err(err) => println!("thread join error: {:?}", err), }); } }