diff --git a/src/elements/state.rs b/src/elements/state.rs index 79c4343..e1b14a3 100644 --- a/src/elements/state.rs +++ b/src/elements/state.rs @@ -1,94 +1,94 @@ -use std::ops::{Deref, DerefMut}; +use std::{ + fmt::{Debug, Display, Formatter, Result as FmtResult}, + ops::{Deref, DerefMut}, + sync::{Arc, Mutex, MutexGuard}, +}; use crate::dependency::DependencyHandler; -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct State { - pub value: *mut T, - dependencies: *mut usize, - changed: *mut usize, // set to dependencies when the value is changed + inner: Arc>>, } -pub fn use_state(mut v: T) -> State { +#[derive(Debug)] +pub struct Inner { + value: T, + dependencies: usize, + changed: usize, +} + +pub fn use_state(v: T) -> State { State { - value: &mut v, - dependencies: &mut 0, - changed: &mut 0, + inner: Arc::new(Mutex::new(Inner { + value: v, + dependencies: 0, + changed: 0, + })), + } +} + +impl State { + /// Gets the cloned value, recommended for preventing deadlocks + pub fn get_dl(&self) -> T { + self.inner.lock().unwrap().value.clone() } } impl State { - pub fn set(&self, v: T) { - unsafe { - *self.value = v; - } - - self.change(); + /// Gets a lock on the state for read/write access. + pub fn get(&self) -> MutexGuard<'_, Inner> { + self.inner.lock().unwrap() } - pub fn change(&self) { - unsafe { - *self.changed = *self.dependencies; - } + /// Sets the value and marks it as changed. + pub fn set(&self, v: T) { + let mut inner = self.inner.lock().unwrap(); + inner.value = v; + inner.changed = inner.dependencies; + } + + /// Marks the state as updated. + pub fn update(&self) { + let mut inner = self.inner.lock().unwrap(); + inner.changed = inner.dependencies; } } -impl DependencyHandler for State { +impl DependencyHandler for State { fn check(&self) -> bool { - unsafe { - let i = *self.changed > 0; - if i { - *self.changed -= 1; - } - i + let mut inner = self.inner.lock().unwrap(); + let i = inner.changed > 0; + if i { + inner.changed -= 1; } + i } fn add(&self) { - unsafe { - *self.dependencies += 1; - } + let mut inner = self.inner.lock().unwrap(); + inner.dependencies += 1; } } -impl std::fmt::Display for State { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "{}", unsafe { &*self.value }) +impl Display for State { + fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult { + let inner = self.inner.lock().unwrap(); + write!(f, "{}", inner.value) } } -unsafe impl Send for State {} -unsafe impl Sync for State {} - -impl Deref for State { +impl Deref for Inner { type Target = T; + fn deref(&self) -> &Self::Target { - unsafe { &*self.value } + &self.value } } -impl DerefMut for State { +impl DerefMut for Inner { fn deref_mut(&mut self) -> &mut Self::Target { - unsafe { - self.change(); - - &mut *self.value - } - } -} - -impl Clone for State { - fn clone(&self) -> Self { - Self { - value: self.value, - dependencies: self.dependencies, - changed: self.changed, - } - } - - fn clone_from(&mut self, source: &Self) { - self.changed = source.changed; - self.dependencies = source.dependencies; - self.value = source.value; + self.changed = self.dependencies; + &mut self.value } } diff --git a/src/main.rs b/src/main.rs index ff572c2..530bffe 100644 --- a/src/main.rs +++ b/src/main.rs @@ -4,6 +4,14 @@ fn main() -> std::io::Result<()> { let screen = Screen::new(); let count = use_state(0); + std::thread::spawn({ + let count = count.clone(); + move || loop { + std::thread::sleep(std::time::Duration::from_millis(1000)); + **count.get() += 500; + } + }); + screen .draw( Dependency::new({ @@ -14,11 +22,5 @@ fn main() -> std::io::Result<()> { ) .component(Transform::center()); - std::thread::spawn(move || loop { - std::thread::sleep(std::time::Duration::from_millis(900)); - let c = (*count).clone(); - count.set(c + 1); - }); - screen.run() }