|
@@ -11,10 +11,10 @@ use dioxus_core::{
|
|
prelude::{current_scope_id, has_context, provide_context, schedule_update_any},
|
|
prelude::{current_scope_id, has_context, provide_context, schedule_update_any},
|
|
ScopeId, ScopeState,
|
|
ScopeId, ScopeState,
|
|
};
|
|
};
|
|
-use generational_box::{AnyStorage, Mappable, MappableMut, Storage, SyncStorage, UnsyncStorage};
|
|
|
|
|
|
+use generational_box::{GenerationalBoxId, Mappable, MappableMut, Storage, UnsyncStorage};
|
|
use parking_lot::RwLock;
|
|
use parking_lot::RwLock;
|
|
|
|
|
|
-use crate::{get_effect_stack, CopyValue, Effect, EffectStack};
|
|
|
|
|
|
+use crate::{get_effect_ref, CopyValue, EffectStackRef, EFFECT_STACK};
|
|
|
|
|
|
/// Creates a new Signal. Signals are a Copy state management solution with automatic dependency tracking.
|
|
/// Creates a new Signal. Signals are a Copy state management solution with automatic dependency tracking.
|
|
///
|
|
///
|
|
@@ -91,8 +91,7 @@ pub fn use_signal_sync<T: Send + Sync + 'static>(
|
|
cx: &ScopeState,
|
|
cx: &ScopeState,
|
|
f: impl FnOnce() -> T,
|
|
f: impl FnOnce() -> T,
|
|
) -> Signal<T, UnsyncStorage> {
|
|
) -> Signal<T, UnsyncStorage> {
|
|
- // *cx.use_hook(|| Signal::new(f()))
|
|
|
|
- todo!()
|
|
|
|
|
|
+ *cx.use_hook(|| Signal::new(f()))
|
|
}
|
|
}
|
|
|
|
|
|
#[derive(Clone)]
|
|
#[derive(Clone)]
|
|
@@ -127,14 +126,14 @@ fn current_unsubscriber() -> Unsubscriber {
|
|
#[derive(Default)]
|
|
#[derive(Default)]
|
|
pub(crate) struct SignalSubscribers {
|
|
pub(crate) struct SignalSubscribers {
|
|
pub(crate) subscribers: Vec<ScopeId>,
|
|
pub(crate) subscribers: Vec<ScopeId>,
|
|
- pub(crate) effect_subscribers: Vec<Effect>,
|
|
|
|
|
|
+ pub(crate) effect_subscribers: Vec<GenerationalBoxId>,
|
|
}
|
|
}
|
|
|
|
|
|
/// The data stored for tracking in a signal.
|
|
/// The data stored for tracking in a signal.
|
|
pub struct SignalData<T> {
|
|
pub struct SignalData<T> {
|
|
pub(crate) subscribers: Arc<RwLock<SignalSubscribers>>,
|
|
pub(crate) subscribers: Arc<RwLock<SignalSubscribers>>,
|
|
pub(crate) update_any: Arc<dyn Fn(ScopeId) + Sync + Send>,
|
|
pub(crate) update_any: Arc<dyn Fn(ScopeId) + Sync + Send>,
|
|
- pub(crate) effect_stack: EffectStack,
|
|
|
|
|
|
+ pub(crate) effect_ref: EffectStackRef,
|
|
pub(crate) value: T,
|
|
pub(crate) value: T,
|
|
}
|
|
}
|
|
|
|
|
|
@@ -208,7 +207,7 @@ impl<T: 'static, S: Storage<SignalData<T>>> Signal<T, S> {
|
|
subscribers: Default::default(),
|
|
subscribers: Default::default(),
|
|
update_any: schedule_update_any().expect("in a virtual dom"),
|
|
update_any: schedule_update_any().expect("in a virtual dom"),
|
|
value,
|
|
value,
|
|
- effect_stack: get_effect_stack(),
|
|
|
|
|
|
+ effect_ref: get_effect_ref(),
|
|
}),
|
|
}),
|
|
}
|
|
}
|
|
}
|
|
}
|
|
@@ -221,7 +220,7 @@ impl<T: 'static, S: Storage<SignalData<T>>> Signal<T, S> {
|
|
subscribers: Default::default(),
|
|
subscribers: Default::default(),
|
|
update_any: schedule_update_any().expect("in a virtual dom"),
|
|
update_any: schedule_update_any().expect("in a virtual dom"),
|
|
value,
|
|
value,
|
|
- effect_stack: get_effect_stack(),
|
|
|
|
|
|
+ effect_ref: get_effect_ref(),
|
|
},
|
|
},
|
|
owner,
|
|
owner,
|
|
),
|
|
),
|
|
@@ -239,12 +238,12 @@ impl<T: 'static, S: Storage<SignalData<T>>> Signal<T, S> {
|
|
&self,
|
|
&self,
|
|
) -> <<S as Storage<SignalData<T>>>::Ref as Mappable<SignalData<T>>>::Mapped<T> {
|
|
) -> <<S as Storage<SignalData<T>>>::Ref as Mappable<SignalData<T>>>::Mapped<T> {
|
|
let inner = self.inner.read();
|
|
let inner = self.inner.read();
|
|
- if let Some(effect) = inner.effect_stack.current() {
|
|
|
|
|
|
+ if let Some(effect) = EFFECT_STACK.with(|stack| stack.current()) {
|
|
let subscribers = inner.subscribers.read();
|
|
let subscribers = inner.subscribers.read();
|
|
- if !subscribers.effect_subscribers.contains(&effect) {
|
|
|
|
|
|
+ if !subscribers.effect_subscribers.contains(&effect.inner.id()) {
|
|
drop(subscribers);
|
|
drop(subscribers);
|
|
let mut subscribers = inner.subscribers.write();
|
|
let mut subscribers = inner.subscribers.write();
|
|
- subscribers.effect_subscribers.push(effect);
|
|
|
|
|
|
+ subscribers.effect_subscribers.push(effect.inner.id());
|
|
}
|
|
}
|
|
} else if let Some(current_scope_id) = current_scope_id() {
|
|
} else if let Some(current_scope_id) = current_scope_id() {
|
|
// only subscribe if the vdom is rendering
|
|
// only subscribe if the vdom is rendering
|
|
@@ -295,18 +294,19 @@ impl<T: 'static, S: Storage<SignalData<T>>> Signal<T, S> {
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ let self_read = &self.inner.read();
|
|
let subscribers = {
|
|
let subscribers = {
|
|
- let self_read = self.inner.read();
|
|
|
|
- let mut effects = &mut self_read.subscribers.write().effect_subscribers;
|
|
|
|
|
|
+ let effects = &mut self_read.subscribers.write().effect_subscribers;
|
|
std::mem::take(&mut *effects)
|
|
std::mem::take(&mut *effects)
|
|
};
|
|
};
|
|
|
|
+ let effect_ref = &self_read.effect_ref;
|
|
for effect in subscribers {
|
|
for effect in subscribers {
|
|
tracing::trace!(
|
|
tracing::trace!(
|
|
"Write on {:?} triggered effect {:?}",
|
|
"Write on {:?} triggered effect {:?}",
|
|
self.inner.value,
|
|
self.inner.value,
|
|
effect
|
|
effect
|
|
);
|
|
);
|
|
- effect.try_run();
|
|
|
|
|
|
+ effect_ref.rerun_effect(effect);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
@@ -328,6 +328,11 @@ impl<T: 'static, S: Storage<SignalData<T>>> Signal<T, S> {
|
|
let mut write = self.write();
|
|
let mut write = self.write();
|
|
f(&mut *write)
|
|
f(&mut *write)
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+ /// Get the generational id of the signal.
|
|
|
|
+ pub fn id(&self) -> generational_box::GenerationalBoxId {
|
|
|
|
+ self.inner.id()
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
impl<T: Clone + 'static, S: Storage<SignalData<T>>> Signal<T, S> {
|
|
impl<T: Clone + 'static, S: Storage<SignalData<T>>> Signal<T, S> {
|