use std::future::Future;
use std::pin::Pin;
use std::sync::Arc;
use std::task::Context;
use std::task::Poll;
use crate::internal::countdown::CountdownState;
use crate::internal::wakerset::WakerToken;
#[derive(Debug)]
pub struct Latch {
state: CountdownState,
}
impl Latch {
pub fn new(count: u32) -> Self {
Self {
state: CountdownState::new(count),
}
}
pub fn count(&self) -> u32 {
self.state.state()
}
pub fn count_down(&self) {
if self.state.decrement(1) {
self.state.wake_all();
}
}
pub fn arrive(&self, n: u32) {
if n != 0 && self.state.decrement(n) {
self.state.wake_all();
}
}
pub fn try_wait(&self) -> Result<(), u32> {
self.state.try_wait()
}
pub async fn wait(&self) {
let fut = LatchWait {
token: None,
latch: self,
};
fut.await
}
pub async fn wait_owned(self: Arc<Self>) {
let fut = OwnedLatchWait {
token: None,
latch: self,
};
fut.await
}
}
impl Latch {
fn intern_poll(&self, token: &mut Option<WakerToken>, cx: &mut Context<'_>) -> Poll<()> {
self.state.poll_wait(token, cx)
}
}
#[must_use = "futures do nothing unless you `.await` or poll them"]
struct LatchWait<'a> {
token: Option<WakerToken>,
latch: &'a Latch,
}
impl Future for LatchWait<'_> {
type Output = ();
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
let Self { token, latch } = self.get_mut();
latch.intern_poll(token, cx)
}
}
impl Drop for LatchWait<'_> {
fn drop(&mut self) {
self.latch.state.unregister(&mut self.token);
}
}
#[must_use = "futures do nothing unless you `.await` or poll them"]
struct OwnedLatchWait {
token: Option<WakerToken>,
latch: Arc<Latch>,
}
impl Future for OwnedLatchWait {
type Output = ();
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
let Self { token, latch } = self.get_mut();
latch.intern_poll(token, cx)
}
}
impl Drop for OwnedLatchWait {
fn drop(&mut self) {
self.latch.state.unregister(&mut self.token);
}
}