use core::{
future::Future,
pin::Pin,
task::{Context, Poll},
};
use futures_core::future::FusedFuture;
use super::channel::Receiver;
pub struct Recv<'a, T> {
receiver: &'a mut Receiver<T>,
done: bool,
}
impl<'a, T> Recv<'a, T> {
#[inline(always)]
pub(super) fn new(receiver: &'a mut Receiver<T>) -> Self {
Self {
receiver,
done: false,
}
}
}
impl<T> Future for Recv<'_, T> {
type Output = Option<T>;
#[inline]
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
let this = self.get_mut();
let chan = this.receiver.chan();
if let Some(item) = chan.pop() {
chan.wake_senders();
this.done = true;
return Poll::Ready(Some(item));
}
if chan.senders() == 0 {
this.done = true;
return Poll::Ready(None);
}
chan.register_recv_waker(cx.waker());
if let Some(item) = chan.pop() {
chan.wake_senders();
this.done = true;
return Poll::Ready(Some(item));
}
if chan.senders() == 0 {
this.done = true;
return Poll::Ready(None);
}
Poll::Pending
}
}
impl<T> FusedFuture for Recv<'_, T> {
#[inline(always)]
fn is_terminated(&self) -> bool {
self.done
}
}
impl<T> Drop for Recv<'_, T> {
#[inline]
fn drop(&mut self) {
if !self.done {
self.receiver.chan().clear_recv_waker();
}
}
}