Improved state management
This commit is contained in:
@@ -34,7 +34,9 @@ fn app(cx: &Arc<Context>) -> Vec<Node> {
|
|||||||
cx.on_event({
|
cx.on_event({
|
||||||
let count = count.clone();
|
let count = count.clone();
|
||||||
move |_cx, _event: &KeyPress| {
|
move |_cx, _event: &KeyPress| {
|
||||||
*count.get() += 1;
|
#[allow(unused_mut)]
|
||||||
|
let mut count = count.get();
|
||||||
|
*count += 1;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
+54
-54
@@ -1,103 +1,103 @@
|
|||||||
use std::{
|
use std::{
|
||||||
fmt::{Debug, Display, Formatter, Result as FmtResult},
|
fmt::{Debug, Display, Formatter, Result as FmtResult},
|
||||||
ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Sub, SubAssign},
|
ops::{Deref, DerefMut},
|
||||||
sync::{Arc, Mutex, MutexGuard},
|
sync::{Arc, Mutex, MutexGuard},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct HookEffect(Arc<Mutex<dyn Fn() + Send + Sync>>);
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct State<T> {
|
pub struct State<T> {
|
||||||
inner: Arc<Mutex<T>>,
|
value: Arc<Mutex<T>>,
|
||||||
|
dependents: Arc<Mutex<Vec<HookEffect>>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Inner<'a, T> {
|
||||||
|
value: MutexGuard<'a, T>,
|
||||||
|
dependents: Arc<Mutex<Vec<HookEffect>>>,
|
||||||
|
updated: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn use_state<T>(v: T) -> State<T> {
|
pub fn use_state<T>(v: T) -> State<T> {
|
||||||
State {
|
State {
|
||||||
inner: Arc::new(Mutex::new(v)),
|
value: Arc::new(Mutex::new(v)),
|
||||||
|
dependents: Arc::new(Mutex::new(Vec::new())),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Clone> State<T> {
|
impl<T: Clone> State<T> {
|
||||||
/// Gets the cloned value, recommended for preventing deadlocks
|
/// Gets the cloned value, recommended for preventing deadlocks
|
||||||
pub fn get_dl(&self) -> T {
|
pub fn get_dl(&self) -> T {
|
||||||
self.inner.lock().unwrap().clone()
|
self.value.lock().unwrap().clone()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> State<T> {
|
impl<T> State<T> {
|
||||||
/// Gets a lock on the state for read/write access.
|
/// Gets a lock on the state for read/write access.
|
||||||
pub fn get(&self) -> MutexGuard<'_, T> {
|
pub fn get(&self) -> Inner<'_, T> {
|
||||||
self.inner.lock().unwrap()
|
Inner {
|
||||||
|
value: self.value.lock().unwrap(),
|
||||||
|
dependents: self.dependents.clone(),
|
||||||
|
updated: false,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sets the value and marks it as changed.
|
/// Sets the value and marks it as changed.
|
||||||
pub fn set(&self, v: T) {
|
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<T: Display> Display for State<T> {
|
impl<T: Display> Display for State<T> {
|
||||||
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
|
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
|
||||||
write!(f, "{}", self.inner.lock().unwrap())
|
write!(f, "{}", self.value.lock().unwrap())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Add<Output = T> + Clone> Add<T> for State<T> {
|
impl Debug for HookEffect {
|
||||||
type Output = T;
|
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
|
||||||
|
write!(f, "HookEffect")
|
||||||
fn add(self, rhs: T) -> Self::Output {
|
|
||||||
let v = self.inner.lock().unwrap().clone();
|
|
||||||
v.add(rhs)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Sub<Output = T> + Clone> Sub<T> for State<T> {
|
impl HookEffect {
|
||||||
type Output = T;
|
pub fn new<F: Fn() + Send + Sync + 'static>(f: F) -> Self {
|
||||||
|
Self(Arc::new(Mutex::new(f)))
|
||||||
|
}
|
||||||
|
|
||||||
fn sub(self, rhs: T) -> Self::Output {
|
pub fn call(&self) {
|
||||||
let v = self.inner.lock().unwrap().clone();
|
(self.0.lock().unwrap())()
|
||||||
v.sub(rhs)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Mul<Output = T> + Clone> Mul<T> for State<T> {
|
impl<T> Drop for Inner<'_, T> {
|
||||||
type Output = T;
|
fn drop(&mut self) {
|
||||||
|
if self.updated {
|
||||||
fn mul(self, rhs: T) -> Self::Output {
|
for d in self.dependents.lock().unwrap().iter() {
|
||||||
let v = self.inner.lock().unwrap().clone();
|
d.call();
|
||||||
v.mul(rhs)
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Div<Output = T> + Clone> Div<T> for State<T> {
|
impl<T> Deref for Inner<'_, T> {
|
||||||
type Output = T;
|
type Target = T;
|
||||||
|
fn deref(&self) -> &Self::Target {
|
||||||
fn div(self, rhs: T) -> Self::Output {
|
&self.value
|
||||||
let v = self.inner.lock().unwrap().clone();
|
|
||||||
v.div(rhs)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Assign
|
impl<T> DerefMut for Inner<'_, T> {
|
||||||
|
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||||
impl<T: AddAssign> AddAssign<T> for State<T> {
|
self.updated = true;
|
||||||
fn add_assign(&mut self, rhs: T) {
|
&mut self.value
|
||||||
self.get().add_assign(rhs);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: SubAssign> SubAssign<T> for State<T> {
|
|
||||||
fn sub_assign(&mut self, rhs: T) {
|
|
||||||
self.get().sub_assign(rhs);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: MulAssign> MulAssign<T> for State<T> {
|
|
||||||
fn mul_assign(&mut self, rhs: T) {
|
|
||||||
self.get().mul_assign(rhs);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: DivAssign> DivAssign<T> for State<T> {
|
|
||||||
fn div_assign(&mut self, rhs: T) {
|
|
||||||
self.get().div_assign(rhs);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user