use std::{collections::HashMap, marker::PhantomData, sync::Arc};
use futures::future::join_all;
use futures::future::select_ok;
use tokio::sync::{Mutex, broadcast, mpsc};
use crate::NodeId;
use super::information_packet::Content;
#[derive(Default)]
pub struct InChannels(pub(crate) HashMap<NodeId, Arc<Mutex<InChannel>>>);
impl InChannels {
pub fn blocking_recv_from(&mut self, id: &NodeId) -> Result<Content, RecvErr> {
match self.get(id) {
Some(channel) => channel.blocking_lock().blocking_recv(),
None => Err(RecvErr::NoSuchChannel),
}
}
pub async fn recv_from(&mut self, id: &NodeId) -> Result<Content, RecvErr> {
match self.get(id) {
Some(channel) => channel.lock().await.recv().await,
None => Err(RecvErr::NoSuchChannel),
}
}
pub async fn recv_any(&mut self) -> Result<(NodeId, Content), RecvErr> {
let mut futures = Vec::new();
let ids: Vec<NodeId> = self.keys();
for id in ids {
let channel = self.get(&id).ok_or(RecvErr::NoSuchChannel)?;
let fut = Box::pin(async move {
let content = channel.lock().await.recv().await?;
Ok::<_, RecvErr>((id, content))
});
futures.push(fut);
}
if futures.is_empty() {
return Err(RecvErr::NoSuchChannel);
}
match select_ok(futures).await {
Ok((result, _)) => Ok(result),
Err(_) => Err(RecvErr::Closed),
}
}
pub fn blocking_map<F, T>(&mut self, mut f: F) -> Vec<T>
where
F: FnMut(Result<Content, RecvErr>) -> T,
{
self.keys()
.into_iter()
.map(|id| f(self.blocking_recv_from(&id)))
.collect()
}
pub async fn map<F, T>(&mut self, f: F) -> Vec<T>
where
F: FnMut(Result<Content, RecvErr>) -> T,
{
let futures = self
.0
.iter_mut()
.map(|(_, c)| async { c.lock().await.recv().await });
join_all(futures).await.into_iter().map(f).collect()
}
pub async fn close_async(&mut self, id: &NodeId) {
if let Some(c) = self.get(id) {
c.lock().await.close();
self.0.remove(id);
}
}
pub fn close(&mut self, id: &NodeId) {
if let Some(c) = self.get(id) {
c.blocking_lock().close();
self.0.remove(id);
}
}
pub(crate) fn insert(&mut self, node_id: NodeId, channel: Arc<Mutex<InChannel>>) {
self.0.insert(node_id, channel);
}
pub(crate) fn close_all(&mut self) {
self.0.values_mut().for_each(|c| c.blocking_lock().close());
}
pub fn get_sender_ids(&self) -> Vec<NodeId> {
self.keys()
}
fn get(&self, id: &NodeId) -> Option<Arc<Mutex<InChannel>>> {
self.0.get(id).cloned()
}
fn keys(&self) -> Vec<NodeId> {
self.0.keys().copied().collect()
}
}
pub enum InChannel {
Mpsc(mpsc::Receiver<Content>),
Bcst(broadcast::Receiver<Content>),
}
impl InChannel {
fn blocking_recv(&mut self) -> Result<Content, RecvErr> {
match self {
InChannel::Mpsc(receiver) => {
if let Some(content) = receiver.blocking_recv() {
Ok(content)
} else {
Err(RecvErr::Closed)
}
}
InChannel::Bcst(receiver) => match receiver.blocking_recv() {
Ok(v) => Ok(v),
Err(e) => match e {
broadcast::error::RecvError::Closed => Err(RecvErr::Closed),
broadcast::error::RecvError::Lagged(x) => Err(RecvErr::Lagged(x)),
},
},
}
}
async fn recv(&mut self) -> Result<Content, RecvErr> {
match self {
InChannel::Mpsc(receiver) => {
if let Some(content) = receiver.recv().await {
Ok(content)
} else {
Err(RecvErr::Closed)
}
}
InChannel::Bcst(receiver) => match receiver.recv().await {
Ok(v) => Ok(v),
Err(e) => match e {
broadcast::error::RecvError::Closed => Err(RecvErr::Closed),
broadcast::error::RecvError::Lagged(x) => Err(RecvErr::Lagged(x)),
},
},
}
}
fn close(&mut self) {
match self {
InChannel::Mpsc(receiver) => receiver.close(),
InChannel::Bcst(_) => (),
}
}
}
#[derive(Default)]
pub struct TypedInChannels<T: Send + Sync + 'static>(
pub(crate) HashMap<NodeId, Arc<Mutex<InChannel>>>,
pub(crate) PhantomData<T>,
);
impl<T: Send + Sync + 'static> TypedInChannels<T> {
pub fn blocking_recv_from(&mut self, id: &NodeId) -> Result<Option<Arc<T>>, RecvErr> {
match self.get(id) {
Some(channel) => {
let content: Content = channel.blocking_lock().blocking_recv()?;
Ok(content.into_inner())
}
None => Err(RecvErr::NoSuchChannel),
}
}
pub async fn recv_from(&mut self, id: &NodeId) -> Result<Option<Arc<T>>, RecvErr> {
match self.get(id) {
Some(channel) => {
let content: Content = channel.lock().await.recv().await?;
Ok(content.into_inner())
}
None => Err(RecvErr::NoSuchChannel),
}
}
pub async fn recv_any(&mut self) -> Result<(NodeId, Option<Arc<T>>), RecvErr> {
let mut futures = Vec::new();
let ids: Vec<NodeId> = self.keys();
for id in ids {
let channel = self.get(&id).ok_or(RecvErr::NoSuchChannel)?;
let fut = Box::pin(async move {
let content: Content = channel.lock().await.recv().await?;
Ok::<_, RecvErr>((id, content.into_inner()))
});
futures.push(fut);
}
if futures.is_empty() {
return Err(RecvErr::NoSuchChannel);
}
match select_ok(futures).await {
Ok((result, _)) => Ok(result),
Err(_) => Err(RecvErr::Closed),
}
}
pub fn blocking_map<F, U>(&mut self, mut f: F) -> Vec<U>
where
F: FnMut(Result<Option<Arc<T>>, RecvErr>) -> U,
{
self.keys()
.into_iter()
.map(|id| f(self.blocking_recv_from(&id)))
.collect()
}
pub async fn map<F, U>(&mut self, f: F) -> Vec<U>
where
F: FnMut(Result<Option<Arc<T>>, RecvErr>) -> U,
{
let futures = self.0.iter_mut().map(|(_, c)| async {
let content: Content = c.lock().await.recv().await?;
Ok(content.into_inner())
});
join_all(futures).await.into_iter().map(f).collect()
}
pub async fn close_async(&mut self, id: &NodeId) {
if let Some(c) = self.get(id) {
c.lock().await.close();
self.0.remove(id);
}
}
pub fn close(&mut self, id: &NodeId) {
if let Some(c) = self.get(id) {
c.blocking_lock().close();
self.0.remove(id);
}
}
fn get(&self, id: &NodeId) -> Option<Arc<Mutex<InChannel>>> {
self.0.get(id).cloned()
}
fn keys(&self) -> Vec<NodeId> {
self.0.keys().copied().collect()
}
}
#[derive(Debug)]
pub enum RecvErr {
NoSuchChannel,
Closed,
Lagged(u64),
}