State management
This commit is contained in:
+56
-56
@@ -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;
|
use crate::dependency::DependencyHandler;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct State<T> {
|
pub struct State<T> {
|
||||||
pub value: *mut T,
|
inner: Arc<Mutex<Inner<T>>>,
|
||||||
dependencies: *mut usize,
|
|
||||||
changed: *mut usize, // set to dependencies when the value is changed
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn use_state<T>(mut v: T) -> State<T> {
|
#[derive(Debug)]
|
||||||
|
pub struct Inner<T> {
|
||||||
|
value: T,
|
||||||
|
dependencies: usize,
|
||||||
|
changed: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn use_state<T>(v: T) -> State<T> {
|
||||||
State {
|
State {
|
||||||
value: &mut v,
|
inner: Arc::new(Mutex::new(Inner {
|
||||||
dependencies: &mut 0,
|
value: v,
|
||||||
changed: &mut 0,
|
dependencies: 0,
|
||||||
|
changed: 0,
|
||||||
|
})),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Clone> State<T> {
|
||||||
|
/// Gets the cloned value, recommended for preventing deadlocks
|
||||||
|
pub fn get_dl(&self) -> T {
|
||||||
|
self.inner.lock().unwrap().value.clone()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> State<T> {
|
impl<T> State<T> {
|
||||||
|
/// Gets a lock on the state for read/write access.
|
||||||
|
pub fn get(&self) -> MutexGuard<'_, Inner<T>> {
|
||||||
|
self.inner.lock().unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Sets the value and marks it as changed.
|
||||||
pub fn set(&self, v: T) {
|
pub fn set(&self, v: T) {
|
||||||
unsafe {
|
let mut inner = self.inner.lock().unwrap();
|
||||||
*self.value = v;
|
inner.value = v;
|
||||||
|
inner.changed = inner.dependencies;
|
||||||
}
|
}
|
||||||
|
|
||||||
self.change();
|
/// Marks the state as updated.
|
||||||
}
|
pub fn update(&self) {
|
||||||
|
let mut inner = self.inner.lock().unwrap();
|
||||||
pub fn change(&self) {
|
inner.changed = inner.dependencies;
|
||||||
unsafe {
|
|
||||||
*self.changed = *self.dependencies;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: std::fmt::Debug> DependencyHandler for State<T> {
|
impl<T: Debug + Send + Sync> DependencyHandler for State<T> {
|
||||||
fn check(&self) -> bool {
|
fn check(&self) -> bool {
|
||||||
unsafe {
|
let mut inner = self.inner.lock().unwrap();
|
||||||
let i = *self.changed > 0;
|
let i = inner.changed > 0;
|
||||||
if i {
|
if i {
|
||||||
*self.changed -= 1;
|
inner.changed -= 1;
|
||||||
}
|
}
|
||||||
i
|
i
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
fn add(&self) {
|
fn add(&self) {
|
||||||
unsafe {
|
let mut inner = self.inner.lock().unwrap();
|
||||||
*self.dependencies += 1;
|
inner.dependencies += 1;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: std::fmt::Display> std::fmt::Display for State<T> {
|
impl<T: Display> Display for State<T> {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
|
||||||
write!(f, "{}", unsafe { &*self.value })
|
let inner = self.inner.lock().unwrap();
|
||||||
|
write!(f, "{}", inner.value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe impl<T> Send for State<T> {}
|
impl<T> Deref for Inner<T> {
|
||||||
unsafe impl<T> Sync for State<T> {}
|
|
||||||
|
|
||||||
impl<T> Deref for State<T> {
|
|
||||||
type Target = T;
|
type Target = T;
|
||||||
|
|
||||||
fn deref(&self) -> &Self::Target {
|
fn deref(&self) -> &Self::Target {
|
||||||
unsafe { &*self.value }
|
&self.value
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> DerefMut for State<T> {
|
impl<T> DerefMut for Inner<T> {
|
||||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||||
unsafe {
|
self.changed = self.dependencies;
|
||||||
self.change();
|
&mut self.value
|
||||||
|
|
||||||
&mut *self.value
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> Clone for State<T> {
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+8
-6
@@ -4,6 +4,14 @@ fn main() -> std::io::Result<()> {
|
|||||||
let screen = Screen::new();
|
let screen = Screen::new();
|
||||||
let count = use_state(0);
|
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
|
screen
|
||||||
.draw(
|
.draw(
|
||||||
Dependency::new({
|
Dependency::new({
|
||||||
@@ -14,11 +22,5 @@ fn main() -> std::io::Result<()> {
|
|||||||
)
|
)
|
||||||
.component(Transform::center());
|
.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()
|
screen.run()
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user