use std::rc::Rc;
use std::cell::RefCell;
use crate::scheduling::Schedule;
use crate::progress::{Timestamp, ChangeBatch, Antichain};
pub trait Operate<T: Timestamp> {
fn local(&self) -> bool { true }
fn inputs(&self) -> usize;
fn outputs(&self) -> usize;
fn initialize(self: Box<Self>) -> (Connectivity<T::Summary>, Rc<RefCell<SharedProgress<T>>>, Box<dyn Schedule>);
fn notify_me(&self) -> &[FrontierInterest];}
#[derive(Ord, PartialOrd, Eq, PartialEq, Copy, Clone, Debug)]
pub enum FrontierInterest {
Never,
IfCapability,
Always,
}
pub type Connectivity<TS> = Vec<PortConnectivity<TS>>;
#[derive(Debug, Clone)]
pub struct PortConnectivityBuilder<TS> {
entries: Vec<(usize, Antichain<TS>)>,
}
impl<TS> Default for PortConnectivityBuilder<TS> {
fn default() -> Self {
Self { entries: Vec::new() }
}
}
impl<TS> PortConnectivityBuilder<TS> {
pub fn insert(&mut self, index: usize, element: TS) {
self.add_port(index, Antichain::from_elem(element));
}
pub fn add_port(&mut self, port: usize, summary: Antichain<TS>) {
if !summary.is_empty() {
self.entries.push((port, summary));
}
}
pub fn freeze(mut self) -> PortConnectivity<TS> where TS : crate::PartialOrder {
self.entries.sort_unstable_by_key(|(port, _)| *port);
let mut entries: Vec<(usize, Antichain<TS>)> = Vec::with_capacity(self.entries.len());
for (port, summary) in self.entries {
match entries.last_mut() {
Some((last, antichain)) if *last == port => {
for element in summary { antichain.insert(element); }
}
_ => { entries.push((port, summary)); }
}
}
PortConnectivity { entries }
}
}
impl<TS> FromIterator<(usize, Antichain<TS>)> for PortConnectivityBuilder<TS> {
fn from_iter<T>(iter: T) -> Self where T: IntoIterator<Item = (usize, Antichain<TS>)> {
Self { entries: iter.into_iter().filter(|(_,p)| !p.is_empty()).collect() }
}
}
#[derive(serde::Serialize, serde::Deserialize, columnar::Columnar, Debug, Clone, Eq, PartialEq)]
pub struct PortConnectivity<TS> {
entries: Vec<(usize, Antichain<TS>)>,
}
impl<TS> Default for PortConnectivity<TS> {
fn default() -> Self {
Self { entries: Vec::new() }
}
}
impl<TS> IntoIterator for PortConnectivity<TS> {
type Item = (usize, Antichain<TS>);
type IntoIter = std::vec::IntoIter<(usize, Antichain<TS>)>;
fn into_iter(self) -> Self::IntoIter { self.entries.into_iter() }
}
impl<TS> PortConnectivity<TS> {
pub fn iter_ports(&self) -> impl Iterator<Item = (usize, &Antichain<TS>)> {
self.entries.iter().map(|(o,p)| (*o, p))
}
pub fn get(&self, index: usize) -> Option<&Antichain<TS>> {
self.entries
.binary_search_by_key(&index, |(port, _)| *port)
.ok()
.map(|position| &self.entries[position].1)
}
}
impl<TS: crate::PartialOrder> FromIterator<(usize, Antichain<TS>)> for PortConnectivity<TS> {
fn from_iter<T>(iter: T) -> Self where T: IntoIterator<Item = (usize, Antichain<TS>)> {
iter.into_iter().collect::<PortConnectivityBuilder<TS>>().freeze()
}
}
#[derive(Debug)]
pub struct SharedProgress<T: Timestamp> {
pub frontiers: Vec<ChangeBatch<T>>,
pub consumeds: Vec<ChangeBatch<T>>,
pub internals: Vec<ChangeBatch<T>>,
pub produceds: Vec<ChangeBatch<T>>,
}
impl<T: Timestamp> SharedProgress<T> {
pub fn new(inputs: usize, outputs: usize) -> Self {
SharedProgress {
frontiers: vec![ChangeBatch::new(); inputs],
consumeds: vec![ChangeBatch::new(); inputs],
internals: vec![ChangeBatch::new(); outputs],
produceds: vec![ChangeBatch::new(); outputs],
}
}
}