use super::Core;
use super::PipelineId;
use super::Progress;
use super::SourceBlocked;
use super::SourceEnd;
impl Core {
pub(super) fn validate(&self) {
for (id, pipe) in self.pipelines.iter().enumerate() {
let Some(pipe) = pipe else { continue };
for (index, &port) in pipe.inlets.iter().enumerate() {
let source = self.arena.get(port).source;
assert!(
source == (SourceEnd::Pipeline { id, inlet: index })
|| self.arena.get(port).closed(),
"port {port} is an inlet of pipeline {id} but its source is {source:?}"
);
}
for &port in &pipe.outlets {
let queue = self.arena.get(port);
assert!(
queue.sink == Some(id) || queue.closed(),
"port {port} is an outlet of pipeline {id} but its sink is {:?}",
queue.sink
);
assert!(
pipe.outlets.len() == 1 || queue.unbounded(),
"pipeline {id} fans out into bounded port {port}, which can deadlock a \
diamond"
);
}
}
let waiting: Vec<_> = self.shares.waiting().collect();
for (port, queue) in self.arena.iter() {
if queue.is_free() || queue.source != SourceEnd::Unclaimed {
continue;
}
assert!(
waiting.contains(&port),
"port {port} has no reader and no split will claim it, so its sink {:?} \
pushes into it for nothing",
queue.sink
);
}
}
pub(super) fn validate_progress(&self, id: PipelineId, progress: &Progress) {
let pipe = self.pipeline(id);
match progress {
Progress::Blocked(SourceBlocked::Inlet(index)) => {
assert!(
*index < pipe.inlets.len(),
"pipeline {id} waits on inlet {index} of {}",
pipe.inlets.len()
);
let port = pipe.inlets[*index];
let queue = self.arena.get(port);
assert!(
!queue.closed(),
"pipeline {id} waits on inlet {index} (port {port}), which is closed"
);
assert!(
queue.has_room(),
"pipeline {id} waits on inlet {index} (port {port}), which is full, so its \
sink {:?} can never push to wake it",
queue.sink
);
}
Progress::Blocked(SourceBlocked::Io) => assert!(
pipe.pending > 0 || !pipe.bytes.is_empty(),
"pipeline {id} waits for a read with none in flight or delivered"
),
Progress::Done => {
for (index, &port) in pipe.inlets.iter().enumerate() {
assert!(
self.arena.get(port).closed(),
"pipeline {id} finished before inlet {index} (port {port}) closed, so \
its sink {:?} would push into a port nobody reads",
self.arena.get(port).sink
);
}
}
Progress::Outlet => {}
}
}
}