59 lines
1.4 KiB
Rust
59 lines
1.4 KiB
Rust
use std::panic::AssertUnwindSafe;
|
|
|
|
#[derive(Debug)]
|
|
pub(super) struct Thread {
|
|
handle: AssertUnwindSafe<Option<std::thread::JoinHandle<()>>>,
|
|
stopper: flume::Sender<()>,
|
|
}
|
|
|
|
pub(super) struct ThreadBuilder {
|
|
name: String,
|
|
}
|
|
|
|
impl ThreadBuilder {
|
|
pub(super) fn spawn<F>(self, func: F) -> Thread
|
|
where
|
|
F: FnOnce(flume::Receiver<()>) + Send + 'static,
|
|
{
|
|
let (stopper, rx) = flume::bounded(1);
|
|
let handle = AssertUnwindSafe(Some(
|
|
std::thread::Builder::new()
|
|
.name(self.name)
|
|
.spawn(move || (func)(rx))
|
|
.expect("Spawned thread"),
|
|
));
|
|
|
|
Thread { handle, stopper }
|
|
}
|
|
}
|
|
|
|
impl Thread {
|
|
pub(super) fn build(name: String) -> ThreadBuilder {
|
|
ThreadBuilder { name }
|
|
}
|
|
|
|
pub(super) fn shutdown(mut self) -> Result<(), Box<dyn std::any::Any + Send + 'static>> {
|
|
self.do_shutdown()
|
|
}
|
|
|
|
pub(super) fn cancel(&self) -> bool {
|
|
self.stopper.try_send(()).is_ok()
|
|
}
|
|
|
|
fn do_shutdown(&mut self) -> Result<(), Box<dyn std::any::Any + Send + 'static>> {
|
|
let _ = self.stopper.send(());
|
|
|
|
if let Some(handle) = self.handle.take() {
|
|
handle.join()
|
|
} else {
|
|
Ok(())
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Drop for Thread {
|
|
fn drop(&mut self) {
|
|
self.do_shutdown().expect("Panick in dropped thread");
|
|
}
|
|
}
|