asyncnal 0.3.1

Fast concurrent & local asyncronous signalling
Documentation
use core::{marker::PhantomData, task::Waker};

use crate::base::{event::EventWaker, signal::{TechnicalCounter, ValidityMarker, ValidityState, WakeQueue}};


pub(crate) struct AsyncLotTemplate<V, C, Q>
{
    inner: Q,
    counter: C,
    _validity: PhantomData<V>
}

impl<V, C, Q> Default for AsyncLotTemplate<V, C, Q>
where 
    C: TechnicalCounter,
    Q: WakeQueue<(EventWaker, V)>
{
    fn default() -> Self {
        Self {
            inner: Q::default(),
            counter: C::default(),
            _validity: PhantomData
        }
    }

}


impl<V, C, Q> AsyncLotTemplate<V, C, Q>
where 
    V: ValidityMarker,
    C: TechnicalCounter,
    Q: WakeQueue<(EventWaker, V)>
{
    #[inline]
    fn park(&self, waker: &EventWaker) -> V {
        self.counter.increment();
        let notifier = V::create();
        self.inner.enqueue((waker.clone(), notifier.clone()));
        notifier
    }
    #[inline]
    fn unpark_one(&self) -> bool {
        if let Some((waker, signal)) = self.try_unpark() {
            if signal.get() == ValidityState::Idle {
                signal.set(ValidityState::ShouldWake);
                waker.wake_by_ref();
                true
            } else {
                self.unpark_one()
            }
        } else {
            false
        }
    }
    fn notify_wait_release(&self) {
        self.counter.decrement()
    }
    fn has_waiters(&self) -> bool {
        self.counter.get() != 0
    }
    fn try_unpark(&self) -> Option<(EventWaker, V)> {
        self.inner.dequeue()
    }
}


pub trait AsyncLotSignature: Default {
    type ValidityMarker: ValidityMarker;

    fn new() -> Self;
    fn park(&self, cx: &EventWaker) -> Self::ValidityMarker;
    fn notify_wait_release(&self);
    fn has_waiters(&self) -> bool;
    fn unpark_one(&self) -> bool;
}

impl<V, C, Q> AsyncLotSignature for AsyncLotTemplate<V, C, Q>
where 
    V: ValidityMarker,
    C: TechnicalCounter,
    Q: WakeQueue<(EventWaker, V)>
{

    type ValidityMarker = V;


    #[inline]
    fn new() -> Self {
        Self::default()
    }
    #[inline]
    fn has_waiters(&self) -> bool {
        AsyncLotTemplate::has_waiters(&self)
    }
    #[inline]
    fn notify_wait_release(&self) {
        AsyncLotTemplate::notify_wait_release(&self);
    }
    #[inline]
    fn park(&self, cx: &EventWaker) -> Self::ValidityMarker {
        AsyncLotTemplate::park(&self, cx)
    }
    #[inline]
    fn unpark_one(&self) -> bool {
        AsyncLotTemplate::unpark_one(&self)
    }
}


macro_rules! impl_async_lot {
    (
        name = $name:ident,
        waker = $waker:ty,
        validity = $vf:ty,
        counter = $counter:ty,
        queue = $queue:ident
    ) => {

        #[repr(transparent)]
        pub struct $name(AsyncLotTemplate<$vf, $counter, $queue<($waker, $vf)>>);


        impl Default for $name {
            fn default() -> Self {
                Self(AsyncLotTemplate::default())
            }
        }

        impl AsyncLotSignature for $name {
            type ValidityMarker = $vf;

            #[inline]
            fn new() -> Self {
                Self(AsyncLotTemplate::new())
            }
            #[inline]
            fn has_waiters(&self) -> bool {
                AsyncLotTemplate::has_waiters(&self.0)
            }
            #[inline]
            fn park(&self, cx: &crate::base::event::EventWaker) -> $vf {
                AsyncLotTemplate::park(&self.0, cx)
            }
            #[inline]
            fn unpark_one(&self) -> bool {
                AsyncLotTemplate::unpark_one(&self.0)
            }
            #[inline]
            fn notify_wait_release(&self) {
                AsyncLotTemplate::notify_wait_release(&self.0)
            }
        }
    };
}

pub(crate) use impl_async_lot;