timely_communication/allocator/zero_copy/
allocator_process.rs1use std::rc::Rc;
4use std::cell::RefCell;
5use std::collections::{VecDeque, HashMap, hash_map::Entry};
6use std::sync::mpsc::{Sender, Receiver};
7
8use timely_bytes::arc::Bytes;
9
10use crate::networking::MessageHeader;
11
12use crate::{Allocate, Push, Pull};
13use crate::allocator::{AllocateBuilder, Exchangeable, PeerBuilder, Thread};
14use crate::allocator::thread::ThreadPusher;
15use crate::allocator::canary::Canary;
16use crate::allocator::zero_copy::bytes_slab::BytesRefill;
17use crate::allocator::zero_copy::spill::SpillPolicyFn;
18use super::bytes_exchange::{BytesPush, BytesPull, SendEndpoint, MergeQueue};
19
20use super::push_pull::{Pusher, Puller, PullerInner};
21
22pub struct ProcessBuilder {
29 index: usize, peers: usize, pushers: Vec<Receiver<MergeQueue>>, pullers: Vec<Sender<MergeQueue>>, refill: BytesRefill,
34 spill: Option<SpillPolicyFn>, }
36
37impl PeerBuilder for ProcessBuilder {
38 type Peer = ProcessBuilder;
39 fn new_vector(count: usize, refill: BytesRefill, spill: Option<SpillPolicyFn>) -> Vec<ProcessBuilder> {
43
44 let (pullers_vec, pushers_vec) = crate::promise_futures(count, count);
46
47 pushers_vec
48 .into_iter()
49 .zip(pullers_vec)
50 .enumerate()
51 .map(|(index, (pushers, pullers))|
52 ProcessBuilder {
53 index,
54 peers: count,
55 pushers,
56 pullers,
57 refill: refill.clone(),
58 spill: spill.clone(),
59 }
60 )
61 .collect()
62 }
63}
64
65impl ProcessBuilder {
66 pub fn build(self) -> ProcessAllocator {
68
69 let mut recvs = Vec::with_capacity(self.peers);
71 for puller in self.pullers.into_iter() {
72 let buzzer = crate::buzzer::Buzzer::default();
73 let (writer, reader) = match self.spill.as_ref() {
74 Some(build_fn) => {
75 let (w, r) = build_fn();
76 MergeQueue::new_pair(buzzer, Some(w), Some(r))
77 }
78 None => MergeQueue::new_pair(buzzer, None, None),
79 };
80 recvs.push(reader);
83 puller.send(writer).expect("Failed to send MergeQueue");
84 }
85
86 let mut sends = Vec::with_capacity(self.peers);
88 for pusher in self.pushers.into_iter() {
89 let queue = pusher.recv().expect("Failed to receive MergeQueue");
90 let sendpoint = SendEndpoint::new(queue, self.refill.clone());
91 sends.push(Rc::new(RefCell::new(sendpoint)));
92 }
93
94 ProcessAllocator {
95 index: self.index,
96 peers: self.peers,
97 events: Rc::new(RefCell::new(Default::default())),
98 canaries: Rc::new(RefCell::new(Vec::new())),
99 channel_id_bound: None,
100 staged: Vec::new(),
101 sends,
102 recvs,
103 to_local: HashMap::new(),
104 refill: self.refill,
105 }
106 }
107}
108
109impl AllocateBuilder for ProcessBuilder {
110 type Allocator = ProcessAllocator;
111 fn build(self) -> Self::Allocator {
113 self.build()
114 }
115
116}
117
118pub struct ProcessAllocator {
120
121 index: usize, peers: usize, events: Rc<RefCell<Vec<usize>>>,
125
126 canaries: Rc<RefCell<Vec<usize>>>,
127
128 channel_id_bound: Option<usize>,
129
130 staged: Vec<Bytes>,
132 sends: Vec<Rc<RefCell<SendEndpoint<MergeQueue>>>>, recvs: Vec<MergeQueue>, to_local: HashMap<usize, Rc<RefCell<VecDeque<Bytes>>>>, refill: BytesRefill, }
137
138struct Fanout {
144 targets: Vec<Rc<RefCell<SendEndpoint<MergeQueue>>>>,
145}
146
147impl BytesPush for Fanout {
148 fn extend<I: IntoIterator<Item=Bytes>>(&mut self, iterator: I) {
149 for bytes in iterator {
150 for target in self.targets.iter() {
151 target.borrow_mut().push_bytes(bytes.clone());
152 }
153 }
154 }
155}
156
157struct BroadcastPusher<T: Exchangeable> {
159 local: ThreadPusher<T>,
160 remote: Option<Pusher<T, Fanout>>,
161}
162
163impl<T: Exchangeable> Push<T> for BroadcastPusher<T> {
164 fn push(&mut self, element: &mut Option<T>) {
165 if let Some(remote) = self.remote.as_mut() { remote.push(element); }
167 self.local.push(element);
168 }
169}
170
171impl ProcessAllocator {
172 fn local_channel<T: Exchangeable>(&mut self, identifier: usize) -> (ThreadPusher<T>, Box<dyn Pull<T>>) {
179 let (local_send, local_recv) = Thread::new_from(identifier, Rc::clone(&self.events));
180 let channel = Rc::clone(self.to_local.entry(identifier).or_default());
181 use crate::allocator::counters::Puller as CountPuller;
182 let canary = Canary::new(identifier, Rc::clone(&self.canaries));
183 let puller = PullerInner::new(Box::new(local_recv), channel, canary);
184 let puller = Box::new(CountPuller::new(puller, identifier, Rc::clone(&self.events)));
185 (local_send, puller)
186 }
187}
188
189impl Allocate for ProcessAllocator {
190 fn index(&self) -> usize { self.index }
191 fn peers(&self) -> usize { self.peers }
192 fn allocate<T: Exchangeable>(&mut self, identifier: usize) -> (Vec<Box<dyn Push<T>>>, Box<dyn Pull<T>>) {
193
194 if let Some(bound) = self.channel_id_bound {
196 assert!(bound < identifier);
197 }
198 self.channel_id_bound = Some(identifier);
199
200 let mut pushes = Vec::<Box<dyn Push<T>>>::with_capacity(self.peers());
201
202 for target_index in 0 .. self.peers() {
203
204 let header = MessageHeader {
206 channel: identifier,
207 source: self.index,
208 target_lower: target_index,
209 target_upper: target_index+1,
210 length: 0,
211 seqno: 0,
212 };
213
214 pushes.push(Box::new(Pusher::new(header, Rc::clone(&self.sends[target_index]))));
216 }
217
218 let channel = Rc::clone(self.to_local.entry(identifier).or_default());
219
220 use crate::allocator::counters::Puller as CountPuller;
221 let canary = Canary::new(identifier, Rc::clone(&self.canaries));
222 let puller = Box::new(CountPuller::new(Puller::new(channel, canary), identifier, Rc::clone(self.events())));
223
224 (pushes, puller)
225 }
226
227 fn broadcast<T: Exchangeable + Clone>(&mut self, identifier: usize) -> (Box<dyn Push<T>>, Box<dyn Pull<T>>) {
228
229 if let Some(bound) = self.channel_id_bound {
231 assert!(bound < identifier);
232 }
233 self.channel_id_bound = Some(identifier);
234
235 let (local, puller) = self.local_channel::<T>(identifier);
236
237 let targets: Vec<_> = (0 .. self.peers).filter(|&target| target != self.index).map(|target| Rc::clone(&self.sends[target])).collect();
239 let remote = if targets.is_empty() { None } else {
240 let header = MessageHeader {
241 channel: identifier,
242 source: self.index,
243 target_lower: 0,
244 target_upper: self.peers,
245 length: 0,
246 seqno: 0,
247 };
248 let endpoint = SendEndpoint::new(Fanout { targets }, self.refill.clone());
249 Some(Pusher::new(header, Rc::new(RefCell::new(endpoint))))
250 };
251
252 (Box::new(BroadcastPusher { local, remote }), puller)
253 }
254
255 #[inline(never)]
257 fn receive(&mut self) {
258
259 let mut canaries = self.canaries.borrow_mut();
261 for dropped_channel in canaries.drain(..) {
262 let _dropped =
263 self.to_local
264 .remove(&dropped_channel)
265 .expect("non-existent channel dropped");
266 }
272 std::mem::drop(canaries);
273
274 let mut events = self.events.borrow_mut();
275
276 for recv in self.recvs.iter_mut() {
277 recv.drain_into(&mut self.staged);
278 }
279
280 for mut bytes in self.staged.drain(..) {
281
282 while !bytes.is_empty() {
285
286 if let Some(header) = MessageHeader::try_read(&bytes[..]) {
287
288 let mut peel = bytes.extract_to(header.required_bytes());
290 let _ = peel.extract_to(header.header_bytes());
291
292 events.push(header.channel);
295
296 match self.to_local.entry(header.channel) {
298 Entry::Vacant(entry) => {
299 if self.channel_id_bound.map(|b| b < header.channel).unwrap_or(true) {
301 entry.insert(Rc::new(RefCell::new(VecDeque::new())))
302 .borrow_mut()
303 .push_back(peel);
304 }
305 }
306 Entry::Occupied(mut entry) => {
307 entry.get_mut().borrow_mut().push_back(peel);
308 }
309 }
310 }
311 else {
312 println!("failed to read full header!");
313 }
314 }
315 }
316 }
317
318 fn release(&mut self) {
320 for send in self.sends.iter_mut() {
322 send.borrow_mut().publish();
323 }
324
325 }
334
335 fn events(&self) -> &Rc<RefCell<Vec<usize>>> {
336 &self.events
337 }
338 fn await_events(&self, duration: Option<std::time::Duration>) {
339 if self.events.borrow().is_empty() {
340 if let Some(duration) = duration {
341 std::thread::park_timeout(duration);
342 }
343 else {
344 std::thread::park();
345 }
346 }
347 }
348}