mirror of
https://github.com/danbulant/mangui
synced 2026-07-07 20:00:35 +00:00
theoretical implementation of stores
This commit is contained in:
parent
3ae14b4efd
commit
bf35e46f24
2 changed files with 115 additions and 0 deletions
|
|
@ -6,6 +6,7 @@ use mangui::nodes::Node;
|
||||||
pub mod component;
|
pub mod component;
|
||||||
pub mod nodes;
|
pub mod nodes;
|
||||||
pub mod invalidator;
|
pub mod invalidator;
|
||||||
|
pub mod store;
|
||||||
|
|
||||||
pub type SharedComponent<T: Component> = Arc<Mutex<T>>;
|
pub type SharedComponent<T: Component> = Arc<Mutex<T>>;
|
||||||
pub type WeakSharedComponent<T: Component> = std::sync::Weak<Mutex<T>>;
|
pub type WeakSharedComponent<T: Component> = std::sync::Weak<Mutex<T>>;
|
||||||
|
|
|
||||||
114
rusalka/src/store/mod.rs
Normal file
114
rusalka/src/store/mod.rs
Normal file
|
|
@ -0,0 +1,114 @@
|
||||||
|
use std::sync::{atomic::AtomicU64, Arc, Mutex, Weak};
|
||||||
|
|
||||||
|
|
||||||
|
/// Unsubscribes from the store when dropped
|
||||||
|
pub trait StoreUnsubscribe: Drop {}
|
||||||
|
|
||||||
|
pub trait ReadableStore {
|
||||||
|
type State;
|
||||||
|
fn get(&self) -> &Self::State;
|
||||||
|
fn subscribe(&self, callback: Box<dyn FnMut(&Self::State) -> ()>) -> Box<dyn StoreUnsubscribe>;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait WritableStore: ReadableStore {
|
||||||
|
fn set(&mut self, state: Self::State);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Listener<T> {
|
||||||
|
hash: u64,
|
||||||
|
callback: Box<dyn FnMut(&T) -> ()>
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ReadableUnsubscribe<T> {
|
||||||
|
listeners: Weak<Mutex<Vec<Listener<T>>>>,
|
||||||
|
hash: u64
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Sized> Drop for ReadableUnsubscribe<T> {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
if let Some(listeners) = self.listeners.upgrade() {
|
||||||
|
let mut listeners = listeners.lock().unwrap();
|
||||||
|
listeners.retain(|listener| listener.hash != self.hash);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> StoreUnsubscribe for ReadableUnsubscribe<T> {}
|
||||||
|
|
||||||
|
pub struct Readable<T> {
|
||||||
|
state: T,
|
||||||
|
listeners: Arc<Mutex<Vec<Listener<T>>>>
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> Readable<T> {
|
||||||
|
pub fn new(state: T) -> Self {
|
||||||
|
Self {
|
||||||
|
state,
|
||||||
|
listeners: Arc::new(Mutex::new(Vec::new()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static CALL_COUNT: AtomicU64 = AtomicU64::new(0);
|
||||||
|
|
||||||
|
impl<T: 'static> ReadableStore for Readable<T> {
|
||||||
|
type State = T;
|
||||||
|
fn get(&self) -> &Self::State {
|
||||||
|
&self.state
|
||||||
|
}
|
||||||
|
fn subscribe(&self, callback: Box<dyn FnMut(&Self::State) -> ()>) -> Box<dyn StoreUnsubscribe> {
|
||||||
|
let hash = CALL_COUNT.fetch_add(1, std::sync::atomic::Ordering::Relaxed);
|
||||||
|
let mut listeners = self.listeners.lock().unwrap();
|
||||||
|
listeners.push(Listener {
|
||||||
|
callback,
|
||||||
|
hash
|
||||||
|
});
|
||||||
|
Box::new(ReadableUnsubscribe {
|
||||||
|
listeners: Arc::downgrade(&self.listeners),
|
||||||
|
hash
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Writable<T> {
|
||||||
|
state: T,
|
||||||
|
listeners: Arc<Mutex<Vec<Listener<T>>>>
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> Writable<T> {
|
||||||
|
pub fn new(state: T) -> Self {
|
||||||
|
Self {
|
||||||
|
state,
|
||||||
|
listeners: Arc::new(Mutex::new(Vec::new()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: 'static> ReadableStore for Writable<T> {
|
||||||
|
type State = T;
|
||||||
|
fn get(&self) -> &Self::State {
|
||||||
|
&self.state
|
||||||
|
}
|
||||||
|
fn subscribe(&self, callback: Box<dyn FnMut(&Self::State) -> ()>) -> Box<dyn StoreUnsubscribe> {
|
||||||
|
let hash = CALL_COUNT.fetch_add(1, std::sync::atomic::Ordering::Relaxed);
|
||||||
|
let mut listeners = self.listeners.lock().unwrap();
|
||||||
|
listeners.push(Listener {
|
||||||
|
callback,
|
||||||
|
hash
|
||||||
|
});
|
||||||
|
Box::new(ReadableUnsubscribe {
|
||||||
|
listeners: Arc::downgrade(&self.listeners),
|
||||||
|
hash
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: 'static> WritableStore for Writable<T> {
|
||||||
|
fn set(&mut self, state: Self::State) {
|
||||||
|
self.state = state;
|
||||||
|
let mut listeners = self.listeners.lock().unwrap();
|
||||||
|
for listener in listeners.iter_mut() {
|
||||||
|
(listener.callback)(&self.state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in a new issue