use core::fmt;
use core::future::poll_fn;
use core::task::{Context, Poll};
use crate::sync::mpsc::{
self,
error::{SendError, TryRecvError, TrySendError},
};
#[track_caller]
pub fn mesh<T: Send>(parties: usize, capacity: usize) -> Vec<Party<T>> {
assert!(capacity > 0, "mpsc bounded channel requires buffer > 0");
let mut senders: Vec<Vec<mpsc::Sender<T>>> =
(0..parties).map(|_| Vec::with_capacity(parties)).collect();
let mut receivers: Vec<Vec<mpsc::Receiver<T>>> =
(0..parties).map(|_| Vec::with_capacity(parties)).collect();
for sending in &mut senders {
for receiving in &mut receivers {
let (tx, rx) = mpsc::channel(capacity);
sending.push(tx);
receiving.push(rx);
}
}
senders
.into_iter()
.zip(receivers)
.enumerate()
.map(|(index, (senders, receivers))| Party {
index,
parties,
ended: vec![false; receivers.len()],
ended_count: 0,
next: 0,
senders,
receivers,
})
.collect()
}
pub struct Party<T> {
index: usize,
parties: usize,
senders: Vec<mpsc::Sender<T>>,
receivers: Vec<mpsc::Receiver<T>>,
ended: Vec<bool>,
ended_count: usize,
next: usize,
}
impl<T> Party<T> {
pub fn index(&self) -> usize {
self.index
}
pub fn parties(&self) -> usize {
self.parties
}
pub fn sender(&self, to: usize) -> Option<&mpsc::Sender<T>> {
self.senders.get(to)
}
pub fn receiver(&mut self, from: usize) -> Option<&mut mpsc::Receiver<T>> {
self.receivers.get_mut(from)
}
pub async fn send_to(&self, to: usize, value: T) -> Result<(), SendError<T>> {
match self.senders.get(to) {
Some(sender) => sender.send(value).await,
None => Err(SendError(value)),
}
}
pub fn try_send_to(&self, to: usize, value: T) -> Result<(), TrySendError<T>> {
match self.senders.get(to) {
Some(sender) => sender.try_send(value),
None => Err(TrySendError::Closed(value)),
}
}
pub fn close_senders(&mut self) {
self.senders.clear();
}
pub async fn recv_from(&mut self, from: usize) -> Option<T> {
match self.receivers.get_mut(from) {
Some(receiver) => receiver.recv().await,
None => None,
}
}
pub async fn recv(&mut self) -> Option<(usize, T)> {
poll_fn(|cx| self.poll_recv(cx)).await
}
pub fn poll_recv(&mut self, cx: &mut Context<'_>) -> Poll<Option<(usize, T)>> {
let n = self.receivers.len();
for step in 0..n {
let from = (self.next + step) % n;
if self.ended[from] {
continue;
}
match self.receivers[from].poll_recv(cx) {
Poll::Ready(Some(value)) => {
self.next = (from + 1) % n;
return Poll::Ready(Some((from, value)));
}
Poll::Ready(None) => self.end(from),
Poll::Pending => {}
}
}
if self.ended_count == n {
Poll::Ready(None)
} else {
Poll::Pending
}
}
pub fn try_recv(&mut self) -> Result<(usize, T), TryRecvError> {
let n = self.receivers.len();
for step in 0..n {
let from = (self.next + step) % n;
if self.ended[from] {
continue;
}
match self.receivers[from].try_recv() {
Ok(value) => {
self.next = (from + 1) % n;
return Ok((from, value));
}
Err(TryRecvError::Disconnected) => self.end(from),
Err(TryRecvError::Empty) => {}
}
}
if self.ended_count == n {
Err(TryRecvError::Disconnected)
} else {
Err(TryRecvError::Empty)
}
}
fn end(&mut self, from: usize) {
self.ended[from] = true;
self.ended_count += 1;
}
pub fn into_parts(self) -> (Vec<mpsc::Sender<T>>, Vec<mpsc::Receiver<T>>) {
(self.senders, self.receivers)
}
}
impl<T> fmt::Debug for Party<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Party")
.field("index", &self.index)
.field("parties", &self.parties)
.finish()
}
}