From b326fc48ed7597d95fee1dde82e14bd2cb1c6434 Mon Sep 17 00:00:00 2001 From: Leo dev Date: Sun, 23 Nov 2025 11:10:07 +0100 Subject: [PATCH] Improved state management --- examples/hello_world.rs | 4 +- src/state.rs | 108 ++++++++++++++++++++-------------------- 2 files changed, 57 insertions(+), 55 deletions(-) diff --git a/examples/hello_world.rs b/examples/hello_world.rs index a15a528..6efba6a 100644 --- a/examples/hello_world.rs +++ b/examples/hello_world.rs @@ -34,7 +34,9 @@ fn app(cx: &Arc) -> Vec { cx.on_event({ let count = count.clone(); move |_cx, _event: &KeyPress| { - *count.get() += 1; + #[allow(unused_mut)] + let mut count = count.get(); + *count += 1; } }); diff --git a/src/state.rs b/src/state.rs index 76621cf..49a21e9 100644 --- a/src/state.rs +++ b/src/state.rs @@ -1,103 +1,103 @@ use std::{ fmt::{Debug, Display, Formatter, Result as FmtResult}, - ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Sub, SubAssign}, + ops::{Deref, DerefMut}, sync::{Arc, Mutex, MutexGuard}, }; +#[derive(Clone)] +pub struct HookEffect(Arc>); + #[derive(Debug, Clone)] pub struct State { - inner: Arc>, + value: Arc>, + dependents: Arc>>, +} + +pub struct Inner<'a, T> { + value: MutexGuard<'a, T>, + dependents: Arc>>, + updated: bool, } pub fn use_state(v: T) -> State { State { - inner: Arc::new(Mutex::new(v)), + value: Arc::new(Mutex::new(v)), + dependents: Arc::new(Mutex::new(Vec::new())), } } impl State { /// Gets the cloned value, recommended for preventing deadlocks pub fn get_dl(&self) -> T { - self.inner.lock().unwrap().clone() + self.value.lock().unwrap().clone() } } impl State { /// Gets a lock on the state for read/write access. - pub fn get(&self) -> MutexGuard<'_, T> { - self.inner.lock().unwrap() + pub fn get(&self) -> Inner<'_, T> { + Inner { + value: self.value.lock().unwrap(), + dependents: self.dependents.clone(), + updated: false, + } } /// Sets the value and marks it as changed. pub fn set(&self, v: T) { - *self.inner.lock().unwrap() = v; + *self.value.lock().unwrap() = v; + self.update(); + } + + pub fn update(&self) { + for d in self.dependents.lock().unwrap().iter() { + d.call(); + } } } impl Display for State { fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult { - write!(f, "{}", self.inner.lock().unwrap()) + write!(f, "{}", self.value.lock().unwrap()) } } -impl + Clone> Add for State { - type Output = T; - - fn add(self, rhs: T) -> Self::Output { - let v = self.inner.lock().unwrap().clone(); - v.add(rhs) +impl Debug for HookEffect { + fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult { + write!(f, "HookEffect") } } -impl + Clone> Sub for State { - type Output = T; +impl HookEffect { + pub fn new(f: F) -> Self { + Self(Arc::new(Mutex::new(f))) + } - fn sub(self, rhs: T) -> Self::Output { - let v = self.inner.lock().unwrap().clone(); - v.sub(rhs) + pub fn call(&self) { + (self.0.lock().unwrap())() } } -impl + Clone> Mul for State { - type Output = T; - - fn mul(self, rhs: T) -> Self::Output { - let v = self.inner.lock().unwrap().clone(); - v.mul(rhs) +impl Drop for Inner<'_, T> { + fn drop(&mut self) { + if self.updated { + for d in self.dependents.lock().unwrap().iter() { + d.call(); + } + } } } -impl + Clone> Div for State { - type Output = T; - - fn div(self, rhs: T) -> Self::Output { - let v = self.inner.lock().unwrap().clone(); - v.div(rhs) +impl Deref for Inner<'_, T> { + type Target = T; + fn deref(&self) -> &Self::Target { + &self.value } } -// Assign - -impl AddAssign for State { - fn add_assign(&mut self, rhs: T) { - self.get().add_assign(rhs); - } -} - -impl SubAssign for State { - fn sub_assign(&mut self, rhs: T) { - self.get().sub_assign(rhs); - } -} - -impl MulAssign for State { - fn mul_assign(&mut self, rhs: T) { - self.get().mul_assign(rhs); - } -} - -impl DivAssign for State { - fn div_assign(&mut self, rhs: T) { - self.get().div_assign(rhs); +impl DerefMut for Inner<'_, T> { + fn deref_mut(&mut self) -> &mut Self::Target { + self.updated = true; + &mut self.value } }