2020-12-01 10:21:39 +01:00
|
|
|
use std::pin::Pin;
|
|
|
|
use std::task::{Poll, Context};
|
|
|
|
use std::sync::Arc;
|
2020-12-01 09:44:18 +01:00
|
|
|
use std::future::Future;
|
|
|
|
|
2020-12-01 10:21:39 +01:00
|
|
|
use smol::Executor;
|
|
|
|
|
|
|
|
use futures::{future::BoxFuture, Stream, StreamExt};
|
2020-12-01 16:06:39 +01:00
|
|
|
use futures::channel::mpsc;
|
|
|
|
use futures_signals::signal::{Signal, MutableSignalCloned, MutableSignal, Mutable};
|
2020-12-01 09:44:18 +01:00
|
|
|
|
|
|
|
use crate::db::machine::MachineState;
|
|
|
|
use crate::registries::Actuator;
|
|
|
|
use crate::config::Settings;
|
|
|
|
use crate::error::Result;
|
|
|
|
|
2020-12-01 16:06:39 +01:00
|
|
|
pub struct Actor<S: Signal> {
|
|
|
|
// FIXME: This should really be a Signal.
|
|
|
|
// But, alas, MutableSignalCloned is itself not `Clone`. For good reason as keeping track of
|
|
|
|
// the changes itself happens in a way that Clone won't work (well).
|
|
|
|
// So, you can't clone it, you can't copy it and you can't get at the variable inside outside
|
|
|
|
// of a task context. In short, using Mutable isn't possible and we would have to write our own
|
|
|
|
// implementation of MutableSignal*'s . Preferably with the correct optimizations for our case
|
|
|
|
// where there is only one consumer. So a mpsc channel that drops all but the last input.
|
|
|
|
rx: mpsc::Receiver<Option<S>>
|
|
|
|
inner: S,
|
2020-12-01 09:44:18 +01:00
|
|
|
}
|
|
|
|
|
2020-12-01 16:06:39 +01:00
|
|
|
pub fn load() {
|
|
|
|
let s = Mutable::new(MachineState::new());
|
2020-12-01 10:21:39 +01:00
|
|
|
|
2020-12-01 16:06:39 +01:00
|
|
|
Ok(())
|
2020-12-01 10:21:39 +01:00
|
|
|
}
|
|
|
|
|
2020-12-01 16:06:39 +01:00
|
|
|
#[must_use = "Signals do nothing unless polled"]
|
|
|
|
pub struct MaybeFlatten<A: Signal, B: Signal> {
|
|
|
|
signal: Option<A>,
|
|
|
|
inner: Option<B>,
|
|
|
|
}
|
2020-12-01 10:21:39 +01:00
|
|
|
|
2020-12-01 16:06:39 +01:00
|
|
|
// Poll parent => Has inner => Poll inner => Output
|
|
|
|
// --------------------------------------------------------
|
|
|
|
// Some(Some(inner)) => => Some(value) => Some(value)
|
|
|
|
// Some(Some(inner)) => => => Pending
|
|
|
|
// Some(None) => => => Pending
|
|
|
|
// None => Some(inner) => Some(value) => Some(value)
|
|
|
|
// None => Some(inner) => None => None
|
|
|
|
// None => Some(inner) => Pending => Pending
|
|
|
|
// None => None => => None
|
|
|
|
// Pending => Some(inner) => Some(value) => Some(value)
|
|
|
|
// Pending => Some(inner) => None => Pending
|
|
|
|
// Pending => Some(inner) => Pending => Pending
|
|
|
|
// Pending => None => => Pending
|
|
|
|
impl<A, B> Signal for MaybeFlatten<A, B>
|
|
|
|
where A: Signal<Item=Option<B>> + Unpin,
|
|
|
|
B: Signal + Unpin,
|
|
|
|
{
|
|
|
|
type Item = B::Item;
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
fn poll_change(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Option<Self::Item>> {
|
2020-12-01 10:21:39 +01:00
|
|
|
let mut this = &mut *self;
|
|
|
|
|
2020-12-01 16:06:39 +01:00
|
|
|
let done = match this.signal.as_mut().map(|signal| Signal::poll_change(Pin::new(signal), cx)) {
|
|
|
|
None => true,
|
|
|
|
Some(Poll::Ready(None)) => {
|
|
|
|
this.signal = None;
|
|
|
|
true
|
|
|
|
},
|
|
|
|
Some(Poll::Ready(Some(new_inner))) => {
|
|
|
|
this.inner = new_inner;
|
|
|
|
false
|
|
|
|
},
|
|
|
|
Some(Poll::Pending) => false,
|
|
|
|
};
|
|
|
|
|
|
|
|
match this.inner.as_mut().map(|inner| Signal::poll_change(Pin::new(inner), cx)) {
|
|
|
|
Some(Poll::Ready(None)) => {
|
|
|
|
this.inner = None;
|
|
|
|
},
|
|
|
|
Some(poll) => {
|
|
|
|
return poll;
|
|
|
|
},
|
|
|
|
None => {},
|
2020-12-01 10:21:39 +01:00
|
|
|
}
|
2020-12-01 09:44:18 +01:00
|
|
|
|
2020-12-01 16:06:39 +01:00
|
|
|
if done {
|
|
|
|
Poll::Ready(None)
|
|
|
|
|
|
|
|
} else {
|
|
|
|
Poll::Pending
|
2020-12-01 10:21:39 +01:00
|
|
|
}
|
2020-12-01 09:44:18 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-12-01 16:06:39 +01:00
|
|
|
#[cfg(test)]
|
|
|
|
mod tests {
|
|
|
|
use super::*;
|
|
|
|
use futures_test::*;
|
|
|
|
use futures_signals::signal::Signal;
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn load_test() {
|
|
|
|
let (a, s, m) = super::load().unwrap();
|
|
|
|
|
|
|
|
let cx = task::panic_context();
|
|
|
|
a.signal.poll_change(&mut cx);
|
|
|
|
}
|
2020-12-01 09:44:18 +01:00
|
|
|
}
|