From f6fd20bb61d41976fa8f84e0fae01503f104da11 Mon Sep 17 00:00:00 2001 From: Evan Almloff Date: Tue, 16 Jan 2024 13:57:31 -0600 Subject: [PATCH] fix signals --- Cargo.lock | 8 ++++++ packages/signals/src/comparer.rs | 12 ++++----- packages/signals/src/effect.rs | 3 +-- packages/signals/src/impls.rs | 44 +++----------------------------- packages/signals/src/rt.rs | 8 +++--- packages/signals/src/selector.rs | 13 ++++------ packages/signals/src/signal.rs | 11 +++----- 7 files changed, 32 insertions(+), 67 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index bc647d375..894ef8201 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2881,11 +2881,17 @@ dependencies = [ "dioxus", "dioxus-core", "dioxus-desktop", + "futures-channel", + "futures-util", "generational-box", + "once_cell", + "parking_lot", + "rustc-hash", "serde", "simple_logger", "tokio", "tracing", + "tracing-subscriber", ] [[package]] @@ -3868,6 +3874,8 @@ dependencies = [ name = "generational-box" version = "0.4.3" dependencies = [ + "criterion 0.3.6", + "parking_lot", "rand 0.8.5", ] diff --git a/packages/signals/src/comparer.rs b/packages/signals/src/comparer.rs index 90b407bba..f13204c1e 100644 --- a/packages/signals/src/comparer.rs +++ b/packages/signals/src/comparer.rs @@ -27,14 +27,14 @@ impl Comparer { if let Some(previous) = previous.take() { if let Some(value) = subscribers.get(&previous) { - value.set(false); + *value.write_unchecked() = false; } } let current = f(); if let Some(value) = subscribers.get(¤t) { - value.set(true); + *value.write_unchecked() = true; } *previous = Some(current); @@ -59,14 +59,14 @@ impl>> Comparer { if let Some(previous) = previous.take() { if let Some(value) = subscribers.get(&previous) { - value.set(false); + *value.write_unchecked() = false; } } let current = f(); if let Some(value) = subscribers.get(¤t) { - value.set(true); + *value.write_unchecked() = true; } *previous = Some(current); @@ -136,6 +136,6 @@ impl>> Copy for Comparer {} /// } /// ``` #[must_use] -pub fn use_comparer(cx: &ScopeState, f: impl FnMut() -> R + 'static) -> Comparer { - *cx.use_hook(move || Comparer::new(f)) +pub fn use_comparer(f: impl FnMut() -> R + 'static) -> Comparer { + use_hook(move || Comparer::new(f)) } diff --git a/packages/signals/src/effect.rs b/packages/signals/src/effect.rs index f24626160..81f22e7bb 100644 --- a/packages/signals/src/effect.rs +++ b/packages/signals/src/effect.rs @@ -7,8 +7,7 @@ use parking_lot::RwLock; use rustc_hash::FxHashMap; use std::fmt::{self, Formatter}; -use crate::use_signal; -use crate::{dependency::Dependency, CopyValue}; +use crate::CopyValue; thread_local! { pub(crate)static EFFECT_STACK: EffectStack = EffectStack::default(); diff --git a/packages/signals/src/impls.rs b/packages/signals/src/impls.rs index d6f4c4933..2fdf8aeef 100644 --- a/packages/signals/src/impls.rs +++ b/packages/signals/src/impls.rs @@ -177,42 +177,6 @@ macro_rules! write_impls { self.with_mut(|v| v.split_off(at)) } } - - impl $ty> { - /// Takes the value out of the Option. - #[track_caller] - pub fn take(&mut self) -> Option { - self.with_mut(|v| v.take()) - } - - /// Replace the value in the Option. - #[track_caller] - pub fn replace(&mut self, value: T) -> Option { - self.with_mut(|v| v.replace(value)) - } - - /// Gets the value out of the Option, or inserts the given value if the Option is empty. - #[track_caller] - pub fn get_or_insert(&mut self, default: T) -> GenerationalRef { - self.get_or_insert_with(|| default) - } - - /// Gets the value out of the Option, or inserts the value returned by the given function if the Option is empty. - #[track_caller] - pub fn get_or_insert_with( - &mut self, - default: impl FnOnce() -> T, - ) -> GenerationalRef { - let borrow = self.read(); - if borrow.is_none() { - drop(borrow); - self.write_unchecked().replace(default()); - GenerationalRef::map(self.read(), |v| v.as_ref().unwrap()) - } else { - GenerationalRef::map(borrow, |v| v.as_ref().unwrap()) - } - } - } }; } @@ -324,23 +288,23 @@ write_impls!(Signal, Storage>, Storage>>); impl>>> Signal, S> { /// Takes the value out of the Option. - pub fn take(&self) -> Option { + pub fn take(&mut self) -> Option { self.with_mut(|v| v.take()) } /// Replace the value in the Option. - pub fn replace(&self, value: T) -> Option { + pub fn replace(&mut self, value: T) -> Option { self.with_mut(|v| v.replace(value)) } /// Gets the value out of the Option, or inserts the given value if the Option is empty. - pub fn get_or_insert(&self, default: T) -> <>>>::Mapped> as Mappable>>::Mapped{ + pub fn get_or_insert(&mut self, default: T) -> <>>>::Mapped> as Mappable>>::Mapped{ self.get_or_insert_with(|| default) } /// Gets the value out of the Option, or inserts the value returned by the given function if the Option is empty. pub fn get_or_insert_with( - &self, + &mut self, default: impl FnOnce() -> T, ) -><>>>::Mapped> as Mappable>>::Mapped{ let borrow = self.read(); diff --git a/packages/signals/src/rt.rs b/packages/signals/src/rt.rs index 5b32a6cb1..0cb8f1992 100644 --- a/packages/signals/src/rt.rs +++ b/packages/signals/src/rt.rs @@ -23,7 +23,7 @@ fn current_owner, T>() -> Rc> { Some(rt) => rt, None => { let owner = Rc::new(S::owner()); - provide_context(owner).expect("in a virtual dom") + provide_context(owner) } }, } @@ -34,7 +34,7 @@ fn owner_in_scope, T>(scope: ScopeId) -> Rc> { Some(rt) => rt, None => { let owner = Rc::new(S::owner()); - provide_context_to_scope(scope, owner).expect("in a virtual dom") + scope.provide_context(owner) } } } @@ -159,7 +159,7 @@ impl> CopyValue { self.value.try_write() } - pub fn write_unchecked(&self) -> GenerationalRefMut { + pub fn write_unchecked(&self) -> S::Mut { self.value.write() } @@ -205,7 +205,7 @@ impl> PartialEq for CopyValue { } } -impl> Deref for CopyValue { +impl> Deref for CopyValue { type Target = dyn Fn() -> T; fn deref(&self) -> &Self::Target { diff --git a/packages/signals/src/selector.rs b/packages/signals/src/selector.rs index bf370d350..1328d3bde 100644 --- a/packages/signals/src/selector.rs +++ b/packages/signals/src/selector.rs @@ -72,14 +72,13 @@ pub fn use_maybe_sync_selector>>( #[track_caller] #[must_use = "Consider using `use_effect` to rerun a callback when dependencies change"] pub fn use_selector_with_dependencies( - cx: &ScopeState, dependencies: D, f: impl FnMut(D::Out) -> R + 'static, ) -> ReadOnlySignal where D::Out: 'static, { - use_maybe_sync_selector_with_dependencies(cx, dependencies, f) + use_maybe_sync_selector_with_dependencies(dependencies, f) } /// Creates a new Selector that may be sync with some local dependencies. The selector will be run immediately and whenever any signal it reads or any dependencies it tracks changes @@ -105,15 +104,14 @@ pub fn use_maybe_sync_selector_with_dependencies< D: Dependency, S: Storage>, >( - cx: &ScopeState, dependencies: D, mut f: impl FnMut(D::Out) -> R + 'static, ) -> ReadOnlySignal where D::Out: 'static, { - let dependencies_signal = use_signal(cx, || dependencies.out()); - let selector = *cx.use_hook(|| { + let mut dependencies_signal = use_signal(|| dependencies.out()); + let selector = use_hook(|| { maybe_sync_selector(move || { let deref = &*dependencies_signal.read(); f(deref.clone()) @@ -141,7 +139,7 @@ pub fn selector(f: impl FnMut() -> R + 'static) -> ReadOnlySignal< pub fn maybe_sync_selector>>( mut f: impl FnMut() -> R + 'static, ) -> ReadOnlySignal { - let state = Signal:: { + let mut state = Signal:: { inner: CopyValue::invalid(), }; let effect = Effect { @@ -154,8 +152,7 @@ pub fn maybe_sync_selector>>( } state.inner.value.set(SignalData { subscribers: Default::default(), - effect_subscribers: Default::default(), - update_any: schedule_update_any().expect("in a virtual dom"), + update_any: schedule_update_any(), value: f(), effect_ref: get_effect_ref(), }); diff --git a/packages/signals/src/signal.rs b/packages/signals/src/signal.rs index 2c78e178b..585b72caf 100644 --- a/packages/signals/src/signal.rs +++ b/packages/signals/src/signal.rs @@ -104,13 +104,10 @@ pub fn use_signal(f: impl FnOnce() -> T) -> Signal /// ``` #[must_use] #[track_caller] -pub fn use_signal_sync( - cx: &ScopeState, - f: impl FnOnce() -> T, -) -> Signal { +pub fn use_signal_sync(f: impl FnOnce() -> T) -> Signal { #[cfg(debug_assertions)] let caller = std::panic::Location::caller(); - *cx.use_hook(|| { + use_hook(|| { Signal::new_with_caller( f(), #[cfg(debug_assertions)] @@ -467,7 +464,7 @@ impl>> PartialEq for Signal { /// Allow calling a signal with signal() syntax /// /// Currently only limited to copy types, though could probably specialize for string/arc/rc -impl> + 'static> Deref for Signal { +impl> + 'static> Deref for Signal { type Target = dyn Fn() -> T; fn deref(&self) -> &Self::Target { @@ -634,7 +631,7 @@ impl>> PartialEq for ReadOnlySignal { } } -impl> + 'static> Deref for ReadOnlySignal { +impl> + 'static> Deref for ReadOnlySignal { type Target = dyn Fn() -> T; fn deref(&self) -> &Self::Target {