use futures::channel::mpsc;
use futures::never::Never;
use futures::task::{Context, Poll};
use futures::{Future, Stream};
use std::pin::Pin;
#[derive(Debug)]
pub struct Barrier(mpsc::Receiver<Never>);
#[derive(Debug, Clone)]
pub struct BarrierBlock(#[expect(dead_code)] mpsc::Sender<Never>);
impl Barrier {
pub fn new() -> (Self, BarrierBlock) {
let (send, recv) = mpsc::channel(0);
(Self(recv), BarrierBlock(send))
}
}
impl Future for Barrier {
type Output = ();
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
let recv = Pin::new(&mut self.get_mut().0);
recv.poll_next(cx).map(|_| ())
}
}
#[cfg(test)]
mod tests {
use super::*;
use futures::prelude::*;
#[test]
fn drop_single_block_unblocks_barrier() {
let (barrier, _) = Barrier::new();
assert_eq!(barrier.now_or_never(), Some(()));
}
#[test]
fn single_block_blocks_barrier() {
let mut executor = fuchsia_async::TestExecutor::new();
let (mut barrier, block) = Barrier::new();
assert_eq!(executor.run_until_stalled(&mut barrier), Poll::Pending);
drop(block);
assert_eq!(executor.run_until_stalled(&mut barrier), Poll::Ready(()));
}
#[test]
fn block_clone_blocks_barrier() {
let mut executor = fuchsia_async::TestExecutor::new();
let (mut barrier, block) = Barrier::new();
let block_clone = block.clone();
assert_eq!(executor.run_until_stalled(&mut barrier), Poll::Pending);
drop(block);
assert_eq!(executor.run_until_stalled(&mut barrier), Poll::Pending);
drop(block_clone);
assert_eq!(executor.run_until_stalled(&mut barrier), Poll::Ready(()));
}
}