use std::cell::Cell; use std::future::Future; use std::pin::Pin; use std::task::{Context, Poll}; use futures_signals::signal::{MutableSignalRef, ReadOnlyMutable, Signal}; use futures_util::future::BoxFuture; use crate::resources::state::State; mod shelly; pub trait Actor { fn apply(&mut self, state: State) -> BoxFuture<'static, ()>; } fn loader>(cell: &Cell>) -> Option { cell.take() } pub struct ActorDriver { signal: S, actor: Box, future: Option>, } impl> ActorDriver { pub fn new(signal: S, actor: Box) -> Self { Self { signal, actor, future: None, } } } impl Future for ActorDriver where S: Signal + Unpin + Send, { type Output = (); fn poll(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll { // Work until there is no more work to do. loop { // Poll the `apply` future. And ensure it's completed before the next one is started match self.future.as_mut() .map(|future| Future::poll(Pin::new(future), cx)) { // Skip and poll for a new future to do None => { } // This apply future is done, get a new one Some(Poll::Ready(_)) => self.future = None, // This future would block so we return to continue work another time Some(Poll::Pending) => return Poll::Pending, } // Poll the signal and apply any change that happen to the inner Actuator match Pin::new(&mut self.signal).poll_change(cx) { Poll::Pending => return Poll::Pending, Poll::Ready(None) => return Poll::Pending, Poll::Ready(Some(state)) => { // This future MUST be polled before we exit from the Actor::poll because if we // do not do that it will not register the dependency and thus NOT BE POLLED. let f = self.actor.apply(state); self.future.replace(f); } } } } }