use std::{ sync::Arc, task::{Context, Poll}, }; use futures_util::task::AtomicWaker; use rtrb::{Consumer, Producer, PushError, RingBuffer}; pub fn channel(cap: usize) -> (Sender, Receiver) { let (tx, rx) = RingBuffer::new(cap).split(); let waker = Arc::new(AtomicWaker::new()); let sender = Sender { tx, waker: waker.clone(), }; let receiver = Receiver { rx, waker }; (sender, receiver) } pub struct Sender { tx: Producer, waker: Arc, } impl Sender { pub fn send(&mut self, item: T) -> Result<(), T> { match self.tx.push(item) { Ok(_) => { self.waker.wake(); Ok(()) } Err(PushError::Full(item)) => Err(item), } } } pub struct Receiver { rx: Consumer, waker: Arc, } impl Receiver { pub fn poll_recv_unpin(&mut self, cx: &mut Context<'_>) -> Poll { match self.rx.pop() { Ok(item) => Poll::Ready(item), Err(_) => { self.waker.register(cx.waker()); Poll::Pending } } } }