jay-compositor 1.15.0

The Jay compositor
use crate::utils::numcell::NumCell;
use std::cell::Cell;
use std::fmt::Debug;
use std::fmt::Formatter;
use std::pin::Pin;
use std::task::Context;
use std::task::Poll;
use std::task::Waker;

#[derive(Default)]
pub struct AsyncEvent {
    triggers: NumCell<u64>,
    waker: Cell<Option<Waker>>,
}

impl Debug for AsyncEvent {
    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
        f.debug_struct("AsyncEvent")
            .field("triggers", &self.triggers.get())
            .finish_non_exhaustive()
    }
}

impl AsyncEvent {
    pub fn clear(&self) {
        self.triggers.set(0);
        self.waker.take();
    }

    pub fn reset_triggers(&self) {
        self.triggers.set(0);
    }

    pub fn trigger(&self) {
        if self.triggers.fetch_add(1) == 0
            && let Some(waker) = self.waker.take()
        {
            waker.wake();
        }
    }

    pub fn triggered(&self) -> AsyncEventTriggered<'_> {
        AsyncEventTriggered { ae: self }
    }
}

pub struct AsyncEventTriggered<'a> {
    ae: &'a AsyncEvent,
}

impl Future for AsyncEventTriggered<'_> {
    type Output = u64;

    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
        let triggers = self.ae.triggers.replace(0);
        if triggers == 0 {
            self.ae.waker.set(Some(cx.waker().clone()));
            Poll::Pending
        } else {
            Poll::Ready(triggers)
        }
    }
}