use lossyq::spsc::{Sender, Receiver, channel};
use super::super::common::{Task, Reporter, Message, Schedule, IdentifiedReceiver, Direction, new_id};
use super::super::connectable::{Connectable};
use super::super::scheduler::MeasureTime;
pub trait Scatter {
type InputType : Send;
type OutputType : Send;
fn process(
&mut self,
input: &mut Option<IdentifiedReceiver<Self::InputType>>,
output: &mut Vec<Sender<Message<Self::OutputType>>>) -> Schedule;
}
pub struct ScatterWrap<Input: Send, Output: Send> {
name : String,
state : Box<Scatter<InputType=Input,OutputType=Output>+Send>,
input_rx : Option<IdentifiedReceiver<Input>>,
output_tx_vec : Vec<Sender<Message<Output>>>,
p1 : MeasureTime,
}
impl<Input: Send, Output: Send> Connectable for ScatterWrap<Input,Output> {
type Input = Input;
fn input(&mut self) -> &mut Option<IdentifiedReceiver<Input>> {
&mut self.input_rx
}
}
impl<Input: Send, Output: Send> Task for ScatterWrap<Input,Output> {
fn execute(&mut self, reporter: &mut Reporter) -> Schedule {
self.p1.start();
let mut msg_ids = vec![];
for otx in &self.output_tx_vec {
msg_ids.push(otx.seqno());
}
let retval = self.state.process(&mut self.input_rx,
&mut self.output_tx_vec);
let otx_slice = self.output_tx_vec.as_slice();
let ids_slice = msg_ids.as_slice();
for i in 0..msg_ids.len() {
let new_msg_id = otx_slice[i].seqno();
if ids_slice[i] != new_msg_id {
reporter.message_sent(i, new_msg_id);
}
}
self.p1.end();
self.p1.print("Scatter: p1");
retval
}
fn name(&self) -> &String { &self.name }
}
pub fn new<Input: Send, Output: Send>(
name : &str,
output_q_size : usize,
scatter : Box<Scatter<InputType=Input,OutputType=Output>+Send>,
n_channels : usize)
-> (Box<ScatterWrap<Input,Output>>, Vec<Box<Option<IdentifiedReceiver<Output>>>>)
{
let mut tx_vec = vec![];
let mut rx_vec = vec![];
for i in 0..n_channels {
let (output_tx, output_rx) = channel(output_q_size);
tx_vec.push(output_tx);
rx_vec.push(
Box::new(
Some(
IdentifiedReceiver{
id: new_id(String::from(name), Direction::Out, i),
input: output_rx,
}
)
)
);
}
(
Box::new(
ScatterWrap{
name : String::from(name),
state : scatter,
input_rx : None,
output_tx_vec : tx_vec,
p1 : MeasureTime::new(),
}
),
rx_vec
)
}