engine/controllable_thread/src/lib.rs
2024-08-23 13:22:09 +02:00

64 lines
1.7 KiB
Rust

use std::{
error::Error,
sync::mpsc::{channel, Sender, TryRecvError},
thread::sleep,
thread::{self, JoinHandle},
time::Duration,
};
pub struct ControllableThread {
thread: Option<JoinHandle<Result<(), Box<dyn Error + Send + Sync>>>>,
sender: Sender<bool>,
}
impl ControllableThread {
pub fn new<F>(interval: Duration, mut f: F) -> Self
where
F: FnMut() -> Result<(), Box<dyn Error + Send + Sync>> + 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),
});
}
}