use crate::xx::*; use alloc::collections::VecDeque; use core::fmt; #[derive(Debug)] pub struct Channel { items: VecDeque, cap: usize, eventual: Eventual, } #[derive(Debug)] pub struct Sender { imp: Arc>>, } impl Clone for Sender { fn clone(&self) -> Self { Self { imp: self.imp.clone(), } } } #[derive(Debug)] pub struct Receiver { imp: Arc>>, } impl Clone for Receiver { fn clone(&self) -> Self { Self { imp: self.imp.clone(), } } } pub fn channel(cap: usize) -> (Sender, Receiver) { let imp = Channel { items: VecDeque::with_capacity(cap), cap, eventual: Eventual::new(), }; let imparc = Arc::new(Mutex::new(imp)); ( Sender { imp: imparc.clone(), }, Receiver { imp: imparc.clone(), }, ) } #[derive(Debug, PartialEq, Eq)] pub enum TrySendError { Full(T), Disconnected(T), } impl fmt::Display for TrySendError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { TrySendError::Full(_) => { write!(f, "Full") } TrySendError::Disconnected(_) => { write!(f, "Disconnected") } } } } impl Sender { // NOTE: This needs a timeout or you could block a very long time // pub async fn send(&self, msg: T) -> Result<(), SendError> { // xxx // } pub async fn try_send(&self, msg: T) -> Result<(), TrySendError> { let eventual = { let mut inner = self.imp.lock(); if inner.items.len() == inner.cap { return Err(TrySendError::Full(msg)); } let empty = inner.items.is_empty(); inner.items.push_back(msg); if empty { Some(inner.eventual.clone()) } else { None } }; if let Some(e) = eventual { e.resolve().await; } Ok(()) } pub fn capacity(&self) -> usize { self.imp.lock().cap } pub fn is_empty(&self) -> bool { self.imp.lock().items.is_empty() } pub fn is_full(&self) -> bool { let inner = self.imp.lock(); inner.items.len() == inner.cap } pub fn len(&self) -> usize { self.imp.lock().items.len() } } #[derive(Debug, PartialEq, Eq)] pub struct RecvError; #[derive(Debug, PartialEq, Eq)] pub enum TryRecvError { Empty, Disconnected, } impl Receiver { pub async fn recv(&self) -> Result { let eventual = { let inner = self.imp.lock(); inner.eventual.clone() }; while self.is_empty() { eventual.instance_clone(true).await; } Ok(self.imp.lock().items.pop_front().unwrap()) } pub async fn try_recv(&self) -> Result { if self.is_empty() { return Err(TryRecvError::Empty); } Ok(self.imp.lock().items.pop_front().unwrap()) } pub fn capacity(&self) -> usize { self.imp.lock().cap } pub fn is_empty(&self) -> bool { self.imp.lock().items.is_empty() } pub fn is_full(&self) -> bool { let inner = self.imp.lock(); inner.items.len() == inner.cap } pub fn len(&self) -> usize { self.imp.lock().items.len() } }