diff --git a/signals/src/signal.rs b/signals/src/signal.rs index b0d3068..c27fc0e 100644 --- a/signals/src/signal.rs +++ b/signals/src/signal.rs @@ -455,82 +455,93 @@ impl Signal for Flatten pub mod unsync { use super::{Signal, State}; use std::rc::{Rc, Weak}; - use std::cell::RefCell; + use std::cell::{Cell, RefCell}; use futures::task; + use futures::task::Task; - struct Inner { - value: Option, - task: Option, + struct MutableState { + value: A, + receivers: Vec>>, + } + + struct MutableSignalState { + has_changed: Cell, + task: RefCell>, + // TODO change this to Weak later + state: Rc>>, } #[derive(Clone)] - pub struct Sender { - inner: Weak>>, + pub struct Mutable(Rc>>); + + impl Mutable { + pub fn new(value: A) -> Self { + Mutable(Rc::new(RefCell::new(MutableState { + value, + receivers: vec![], + }))) + } + + pub fn set(&self, value: A) { + let mut state = self.0.borrow_mut(); + + state.value = value; + + state.receivers.retain(|receiver| { + if let Some(receiver) = receiver.upgrade() { + receiver.has_changed.set(true); + + if let Some(task) = receiver.task.borrow_mut().take() { + // TODO drop the mutable borrow before calling task.notify() + task.notify(); + } + + true + + } else { + false + } + }); + } } - impl Sender { - pub fn set(&self, value: A) -> Result<(), A> { - if let Some(inner) = self.inner.upgrade() { - let mut inner = inner.borrow_mut(); + impl Mutable { + #[inline] + pub fn get(&self) -> A { + self.0.borrow().value.clone() + } - inner.value = Some(value); + pub fn signal(&self) -> MutableSignal { + let state = Rc::new(MutableSignalState { + has_changed: Cell::new(false), + task: RefCell::new(None), + state: self.0.clone(), + }); - if let Some(task) = inner.task.take() { - drop(inner); - task.notify(); - } + self.0.borrow_mut().receivers.push(Rc::downgrade(&state)); - Ok(()) - - } else { - Err(value) - } + MutableSignal(state) } } - #[derive(Clone)] - pub struct Receiver { - inner: Rc>>, - } + pub struct MutableSignal(Rc>); - impl Signal for Receiver { + impl Signal for MutableSignal { type Item = A; - #[inline] fn poll(&mut self) -> State { - let mut inner = self.inner.borrow_mut(); + if self.0.has_changed.replace(false) { + State::Changed(self.0.state.borrow().value.clone()) - // TODO is this correct ? - match inner.value.take() { - Some(value) => State::Changed(value), - None => { - inner.task = Some(task::current()); - State::NotChanged - }, + } else { + *self.0.task.borrow_mut() = Some(task::current()); + State::NotChanged } } } - - - pub fn mutable(initial_value: A) -> (Sender, Receiver) { - let inner = Rc::new(RefCell::new(Inner { - value: Some(initial_value), - task: None, - })); - - let sender = Sender { - inner: Rc::downgrade(&inner), - }; - - let receiver = Receiver { - inner, - }; - - (sender, receiver) - } }