bffh/src/registries/actuators.rs
Gregor Reitzenstein 7a876a538d Status commit
2020-09-17 21:12:30 +02:00

88 lines
2.2 KiB
Rust

use slog::Logger;
use std::sync::Arc;
use smol::lock::RwLock;
use std::pin::Pin;
use futures::ready;
use futures::prelude::*;
use futures::task::{Context, Poll};
use futures_signals::signal::Signal;
use crate::machine::Status;
use std::collections::HashMap;
#[derive(Clone)]
pub struct Actuators {
inner: Arc<RwLock<Inner>>,
}
pub type ActBox = Box<dyn Actuator + Sync + Send>;
type Inner = HashMap<String, ActBox>;
impl Actuators {
pub fn new() -> Self {
Actuators {
inner: Arc::new(RwLock::new(Inner::new()))
}
}
pub async fn register(&self, name: String, act: ActBox) {
let mut wlock = self.inner.write().await;
// TODO: Log an error or something if that name was already taken
wlock.insert(name, act);
}
pub async fn run<S: Spawn>(&mut self) {
let mut wlock = self.inner.write().await;
for (_name, act) in wlock.into_iter() {
}
}
pub async fn subscribe(&mut self, name: String, signal: StatusSignal) {
let mut wlock = self.inner.write().await;
if let Some(act) = wlock.get_mut(&name) {
act.subscribe(signal);
}
}
}
pub type StatusSignal = Pin<Box<dyn Signal<Item = Status> + Send + Sync>>;
pub trait Actuator: Stream<Item = future::BoxFuture<'static, ()>> {
fn subscribe(&mut self, signal: StatusSignal);
}
// This is merely a proof that Actuator *can* be implemented on a finite, known type. Yay for type
// systems with halting problems.
struct Dummy {
log: Logger,
signal: Option<StatusSignal>
}
impl Actuator for Dummy {
fn subscribe(&mut self, signal: StatusSignal) {
self.signal.replace(signal);
}
}
impl Stream for Dummy {
type Item = future::BoxFuture<'static, ()>;
fn poll_next(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Option<Self::Item>> {
let unpin = Pin::into_inner(self);
if let Some(ref mut s) = unpin.signal {
let status = ready!(Signal::poll_change(Pin::new(s), cx));
info!(unpin.log, "Dummy actuator would set status to {:?}, but is a Dummy", status);
Poll::Ready(Some(Box::pin(futures::future::ready(()))))
} else {
Poll::Pending
}
}
}