extern crate std;
use alloc::sync::Arc;
use alloc::vec::Vec;
use core::sync::atomic::{AtomicBool, AtomicU8, Ordering};
use std::thread::JoinHandle;
use super::{STAGE_PANICKED, STAGE_RUNNING};
pub struct Pipeline {
pub(super) handles: Vec<JoinHandle<()>>,
pub(super) shutdown: Arc<AtomicBool>,
pub(super) statuses: Vec<Arc<AtomicU8>>,
}
impl Pipeline {
pub fn builder() -> super::builder::PipelineBuilder {
super::builder::PipelineBuilder::new()
}
pub fn shutdown(&self) {
self.shutdown.store(true, Ordering::Release);
}
pub fn join(mut self) {
for h in core::mem::take(&mut self.handles) {
let _ = h.join();
}
}
pub fn try_join(mut self) -> Result<(), alloc::boxed::Box<dyn core::any::Any + Send>> {
for h in core::mem::take(&mut self.handles) {
let _ = h.join();
}
let panicked = self.panicked_stages();
if panicked.is_empty() {
Ok(())
} else {
Err(alloc::boxed::Box::new(panicked))
}
}
pub fn panicked_stages(&self) -> Vec<usize> {
self.statuses
.iter()
.enumerate()
.filter(|(_, s)| s.load(Ordering::Acquire) == STAGE_PANICKED)
.map(|(i, _)| i)
.collect()
}
pub fn is_healthy(&self) -> bool {
self.statuses
.iter()
.all(|s| s.load(Ordering::Acquire) == STAGE_RUNNING)
}
pub fn stage_count(&self) -> usize {
self.statuses.len()
}
}
impl Drop for Pipeline {
fn drop(&mut self) {
self.shutdown.store(true, Ordering::Release);
}
}