use std::cell::RefCell; use std::collections::VecDeque; use std::future::Future; use std::mem; use std::pin::Pin; use std::task::{Context, Poll, Waker}; pub struct AsyncQueue { data: RefCell>, waiters: RefCell>, } impl Default for AsyncQueue { fn default() -> Self { Self::new() } } impl AsyncQueue { pub fn new() -> Self { Self { data: RefCell::new(Default::default()), waiters: RefCell::new(vec![]), } } pub fn push(&self, t: T) { self.data.borrow_mut().push_back(t); for waiter in self.waiters.borrow_mut().drain(..) { waiter.wake(); } } pub fn try_pop(&self) -> Option { self.data.borrow_mut().pop_front() } pub fn pop<'a>(&'a self) -> AsyncQueuePop<'a, T> { AsyncQueuePop { queue: self } } pub fn clear(&self) { mem::take(&mut *self.data.borrow_mut()); mem::take(&mut *self.waiters.borrow_mut()); } } pub struct AsyncQueuePop<'a, T> { queue: &'a AsyncQueue, } impl<'a, T> Future for AsyncQueuePop<'a, T> { type Output = T; fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { if let Some(t) = self.queue.try_pop() { Poll::Ready(t) } else { self.queue.waiters.borrow_mut().push(cx.waker().clone()); Poll::Pending } } }