use std::any::Any;
use std::fmt::Debug;
use std::marker::PhantomData;
use std::sync::atomic::{self, AtomicBool};
use std::sync::Arc;
use std::thread::JoinHandle;
#[derive(Debug)]
pub struct TerminableThreads<T, const N: usize> {
pub(crate) _threads: [JoinHandle<T>; N],
pub(crate) _terminate_flag: Arc<AtomicBool>,
}
impl<T, const N: usize> TerminableThreads<T, N> {
pub fn build() -> (TerminableThreadsBuilder<T, N>, Arc<AtomicBool>) {
TerminableThreadsBuilder::new()
}
pub fn terminate(&self) {
self._terminate_flag
.as_ref()
.store(true, atomic::Ordering::SeqCst);
}
pub fn join(
self,
signal_terminate: bool,
) -> [Result<T, Box<dyn Any + Send + 'static>>; N] {
if signal_terminate {
self.terminate();
}
self._threads.map(JoinHandle::join)
}
}
#[derive(Debug)]
pub struct TerminableThreadsBuilder<T, const N: usize> {
terminate_flag: Arc<AtomicBool>,
_marker: PhantomData<T>,
}
impl<T, const N: usize> TerminableThreadsBuilder<T, N> {
pub fn new() -> (Self, Arc<AtomicBool>) {
let flag = Arc::new(AtomicBool::new(false));
(
Self {
terminate_flag: Arc::clone(&flag),
_marker: PhantomData,
},
flag,
)
}
pub fn build_with_threads(self, threads: [JoinHandle<T>; N]) -> TerminableThreads<T, N> {
TerminableThreads {
_terminate_flag: self.terminate_flag,
_threads: threads,
}
}
}