use crate::modules::input::{Token, token};
use crate::{
futures::task::{
Nothing, Task,
sealed::{self, Step},
},
modules::{
input::{self, Receives},
mailbox::Mailbox,
},
};
use std::{marker::PhantomData, sync::Arc};
pub(crate) struct Gated<F, T, M> {
inner: F,
mailbox: Arc<Mailbox<T>>,
_marker: PhantomData<fn() -> M>,
}
impl<F, T, M> Gated<F, T, M> {
pub(crate) fn new(inner: F, mailbox: Arc<Mailbox<T>>) -> Self {
Self {
inner,
mailbox,
_marker: PhantomData,
}
}
}
impl<F, T, M> Clone for Gated<F, T, M>
where
F: Clone,
{
fn clone(&self) -> Self {
Self {
inner: self.inner.clone(),
mailbox: Arc::clone(&self.mailbox),
_marker: PhantomData,
}
}
}
impl<F, T, M> Drop for Gated<F, T, M> {
fn drop(&mut self) {
if self.mailbox.gate().finished() {
self.mailbox.clear();
}
}
}
impl<F, T, M> sealed::Sealed for Gated<F, T, M> {}
impl<F, T, M> Task for Gated<F, T, M>
where
F: Task,
F::Input: Receives<T, M>,
T: Send + 'static,
M: 'static,
{
type Output = F::Output;
type Input = Nothing;
#[inline(always)]
fn execute(&self, _token: Token, reactor_id: i32, task_id: usize) -> Self::Output {
self.inner.execute(token(), reactor_id, task_id)
}
fn prepare(&mut self, _token: Token) {
self.mailbox.gate().begin();
<F::Input as Receives<T, M>>::deliver(input::token(), &mut self.inner, &self.mailbox);
self.inner.prepare(token());
}
#[inline(always)]
fn blocking(&self, _token: Token) -> bool {
self.inner.blocking(token())
}
#[inline(always)]
fn step(&mut self, _token: Token, reactor_id: i32, task_id: usize) -> Step<Self::Output> {
self.inner.step(token(), reactor_id, task_id)
}
}