use std::rc::Rc;
use std::cell::RefCell;
use std::collections::{VecDeque, HashMap, hash_map::Entry};
use std::sync::mpsc::{Sender, Receiver};
use timely_bytes::arc::Bytes;
use crate::networking::MessageHeader;
use crate::{Allocate, Push, Pull};
use crate::allocator::{AllocateBuilder, Exchangeable, PeerBuilder};
use crate::allocator::canary::Canary;
use crate::allocator::zero_copy::bytes_slab::BytesRefill;
use super::bytes_exchange::{BytesPull, SendEndpoint, MergeQueue};
use super::push_pull::{Pusher, Puller};
pub struct ProcessBuilder {
index: usize, peers: usize, pushers: Vec<Receiver<MergeQueue>>, pullers: Vec<Sender<MergeQueue>>, refill: BytesRefill,
}
impl PeerBuilder for ProcessBuilder {
type Peer = ProcessBuilder;
fn new_vector(count: usize, refill: BytesRefill) -> Vec<ProcessBuilder> {
let (pullers_vec, pushers_vec) = crate::promise_futures(count, count);
pushers_vec
.into_iter()
.zip(pullers_vec)
.enumerate()
.map(|(index, (pushers, pullers))|
ProcessBuilder {
index,
peers: count,
pushers,
pullers,
refill: refill.clone(),
}
)
.collect()
}
}
impl ProcessBuilder {
pub fn build(self) -> ProcessAllocator {
let mut recvs = Vec::with_capacity(self.peers);
for puller in self.pullers.into_iter() {
let buzzer = crate::buzzer::Buzzer::default();
let queue = MergeQueue::new(buzzer);
puller.send(queue.clone()).expect("Failed to send MergeQueue");
recvs.push(queue.clone());
}
let mut sends = Vec::with_capacity(self.peers);
for pusher in self.pushers.into_iter() {
let queue = pusher.recv().expect("Failed to receive MergeQueue");
let sendpoint = SendEndpoint::new(queue, self.refill.clone());
sends.push(Rc::new(RefCell::new(sendpoint)));
}
ProcessAllocator {
index: self.index,
peers: self.peers,
events: Rc::new(RefCell::new(Default::default())),
canaries: Rc::new(RefCell::new(Vec::new())),
channel_id_bound: None,
staged: Vec::new(),
sends,
recvs,
to_local: HashMap::new(),
}
}
}
impl AllocateBuilder for ProcessBuilder {
type Allocator = ProcessAllocator;
fn build(self) -> Self::Allocator {
self.build()
}
}
pub struct ProcessAllocator {
index: usize, peers: usize,
events: Rc<RefCell<Vec<usize>>>,
canaries: Rc<RefCell<Vec<usize>>>,
channel_id_bound: Option<usize>,
staged: Vec<Bytes>,
sends: Vec<Rc<RefCell<SendEndpoint<MergeQueue>>>>, recvs: Vec<MergeQueue>, to_local: HashMap<usize, Rc<RefCell<VecDeque<Bytes>>>>, }
impl Allocate for ProcessAllocator {
fn index(&self) -> usize { self.index }
fn peers(&self) -> usize { self.peers }
fn allocate<T: Exchangeable>(&mut self, identifier: usize) -> (Vec<Box<dyn Push<T>>>, Box<dyn Pull<T>>) {
if let Some(bound) = self.channel_id_bound {
assert!(bound < identifier);
}
self.channel_id_bound = Some(identifier);
let mut pushes = Vec::<Box<dyn Push<T>>>::with_capacity(self.peers());
for target_index in 0 .. self.peers() {
let header = MessageHeader {
channel: identifier,
source: self.index,
target_lower: target_index,
target_upper: target_index+1,
length: 0,
seqno: 0,
};
pushes.push(Box::new(Pusher::new(header, Rc::clone(&self.sends[target_index]))));
}
let channel = Rc::clone(self.to_local.entry(identifier).or_default());
use crate::allocator::counters::Puller as CountPuller;
let canary = Canary::new(identifier, Rc::clone(&self.canaries));
let puller = Box::new(CountPuller::new(Puller::new(channel, canary), identifier, Rc::clone(self.events())));
(pushes, puller)
}
#[inline(never)]
fn receive(&mut self) {
let mut canaries = self.canaries.borrow_mut();
for dropped_channel in canaries.drain(..) {
let _dropped =
self.to_local
.remove(&dropped_channel)
.expect("non-existent channel dropped");
}
std::mem::drop(canaries);
let mut events = self.events.borrow_mut();
for recv in self.recvs.iter_mut() {
recv.drain_into(&mut self.staged);
}
for mut bytes in self.staged.drain(..) {
while !bytes.is_empty() {
if let Some(header) = MessageHeader::try_read(&bytes[..]) {
let mut peel = bytes.extract_to(header.required_bytes());
let _ = peel.extract_to(header.header_bytes());
events.push(header.channel);
match self.to_local.entry(header.channel) {
Entry::Vacant(entry) => {
if self.channel_id_bound.map(|b| b < header.channel).unwrap_or(true) {
entry.insert(Rc::new(RefCell::new(VecDeque::new())))
.borrow_mut()
.push_back(peel);
}
}
Entry::Occupied(mut entry) => {
entry.get_mut().borrow_mut().push_back(peel);
}
}
}
else {
println!("failed to read full header!");
}
}
}
}
fn release(&mut self) {
for send in self.sends.iter_mut() {
send.borrow_mut().publish();
}
}
fn events(&self) -> &Rc<RefCell<Vec<usize>>> {
&self.events
}
fn await_events(&self, duration: Option<std::time::Duration>) {
if self.events.borrow().is_empty() {
if let Some(duration) = duration {
std::thread::park_timeout(duration);
}
else {
std::thread::park();
}
}
}
}