diff --git a/examples/async-demo/src/lib.rs b/examples/async-demo/src/lib.rs index dc919563b..9f694c548 100644 --- a/examples/async-demo/src/lib.rs +++ b/examples/async-demo/src/lib.rs @@ -30,7 +30,7 @@ pub fn async_example() -> impl IntoView { let times = move || { trigger.track(); - async move { (a2.await.to_string(), "test") } //{ (a2.await.to_string(), " and ", b2.await.to_string()) } + async move { (b2.await, a2.await, " and ") } .suspend() .with_fallback("Loading...") .track() diff --git a/reactive_graph/Cargo.toml b/reactive_graph/Cargo.toml index bd2788473..cdffb8643 100644 --- a/reactive_graph/Cargo.toml +++ b/reactive_graph/Cargo.toml @@ -16,6 +16,7 @@ guardian = "1" [dev-dependencies] tokio = { version = "1", features = ["rt-multi-thread", "time", "macros"] } +any_spawner = { workspace = true, features = ["tokio"] } [features] nightly = [] diff --git a/reactive_graph/src/computed/arc_memo.rs b/reactive_graph/src/computed/arc_memo.rs index e01f95e45..79af876d3 100644 --- a/reactive_graph/src/computed/arc_memo.rs +++ b/reactive_graph/src/computed/arc_memo.rs @@ -4,7 +4,7 @@ use crate::{ AnySource, AnySubscriber, ReactiveNode, Source, Subscriber, ToAnySource, ToAnySubscriber, }, - signal::MappedSignalReadGuard, + signal::guards::{Mapped, Plain, ReadGuard}, traits::{DefinedAt, ReadUntracked}, }; use core::fmt::Debug; @@ -159,15 +159,16 @@ impl Subscriber for ArcMemo { } impl ReadUntracked for ArcMemo { - type Value = MappedSignalReadGuard, T>; + type Value = ReadGuard>, T>>; fn try_read_untracked(&self) -> Option { self.update_if_necessary(); - MappedSignalReadGuard::try_new(Arc::clone(&self.inner), |t| { + Mapped::try_new(Arc::clone(&self.inner), |t| { // safe to unwrap here because update_if_necessary // guarantees the value is Some t.value.as_ref().unwrap() }) + .map(ReadGuard::new) } } diff --git a/reactive_graph/src/computed/async_derived/arc_async_derived.rs b/reactive_graph/src/computed/async_derived/arc_async_derived.rs index 594aed639..2635debe7 100644 --- a/reactive_graph/src/computed/async_derived/arc_async_derived.rs +++ b/reactive_graph/src/computed/async_derived/arc_async_derived.rs @@ -9,7 +9,7 @@ use crate::{ SubscriberSet, ToAnySource, ToAnySubscriber, }, owner::Owner, - signal::SignalReadGuard, + signal::guards::{Plain, ReadGuard}, traits::{DefinedAt, ReadUntracked}, }; use any_spawner::Executor; @@ -222,10 +222,10 @@ impl ArcAsyncDerived { } impl ReadUntracked for ArcAsyncDerived { - type Value = SignalReadGuard>; + type Value = ReadGuard, Plain>>; fn try_read_untracked(&self) -> Option { - SignalReadGuard::try_new(Arc::clone(&self.value)) + Plain::try_new(Arc::clone(&self.value)).map(ReadGuard::new) } } diff --git a/reactive_graph/src/computed/async_derived/async_derived.rs b/reactive_graph/src/computed/async_derived/async_derived.rs index 76d9b218d..81075f94a 100644 --- a/reactive_graph/src/computed/async_derived/async_derived.rs +++ b/reactive_graph/src/computed/async_derived/async_derived.rs @@ -7,7 +7,7 @@ use crate::{ ToAnySource, ToAnySubscriber, }, owner::{Stored, StoredData}, - signal::{MappedSignalReadGuard, SignalReadGuard}, + signal::guards::{Mapped, Plain, ReadGuard}, traits::{DefinedAt, ReadUntracked}, unwrap_signal, }; @@ -136,7 +136,7 @@ impl DefinedAt for AsyncDerived { } impl IntoFuture for AsyncDerived { - type Output = MappedSignalReadGuard, T>; + type Output = ReadGuard>, T>>; type IntoFuture = AsyncDerivedFuture; #[track_caller] @@ -147,7 +147,7 @@ impl IntoFuture for AsyncDerived { } impl ReadUntracked for AsyncDerived { - type Value = SignalReadGuard>; + type Value = ReadGuard, Plain>>; fn try_read_untracked(&self) -> Option { self.get_value().map(|inner| inner.read_untracked()) diff --git a/reactive_graph/src/computed/async_derived/future_impls.rs b/reactive_graph/src/computed/async_derived/future_impls.rs index fe18dd406..43c5b7fb9 100644 --- a/reactive_graph/src/computed/async_derived/future_impls.rs +++ b/reactive_graph/src/computed/async_derived/future_impls.rs @@ -1,7 +1,7 @@ use super::{ArcAsyncDerived, AsyncState}; use crate::{ graph::{AnySource, ToAnySource}, - signal::{MappedSignalReadGuard, SignalReadGuard}, + signal::guards::{Mapped, Plain, ReadGuard}, traits::Track, }; use or_poisoned::OrPoisoned; @@ -45,7 +45,7 @@ pub struct AsyncDerivedFuture { } impl IntoFuture for ArcAsyncDerived { - type Output = MappedSignalReadGuard, T>; + type Output = ReadGuard>, T>>; type IntoFuture = AsyncDerivedFuture; fn into_future(self) -> Self::IntoFuture { @@ -58,29 +58,27 @@ impl IntoFuture for ArcAsyncDerived { } impl Future for AsyncDerivedFuture { - type Output = MappedSignalReadGuard, T>; + type Output = ReadGuard>, T>>; fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { let waker = cx.waker(); self.source.track(); - let value = SignalReadGuard::try_new(Arc::clone(&self.value)) - .expect("lock poisoned"); + let value = + Plain::try_new(Arc::clone(&self.value)).expect("lock poisoned"); match &*value { AsyncState::Loading | AsyncState::Reloading(_) => { self.wakers.write().or_poisoned().push(waker.clone()); Poll::Pending } - AsyncState::Complete(_) => Poll::Ready( - MappedSignalReadGuard::try_new( - Arc::clone(&self.value), - |inner| match inner { + AsyncState::Complete(_) => { + Poll::Ready(ReadGuard::new(Mapped::new(value, |inner| { + match inner { AsyncState::Complete(value) => value, // we've just checked this value is Complete _ => unreachable!(), - }, - ) - .expect("lock poisoned"), - ), + } + }))) + } } } } diff --git a/reactive_graph/src/computed/inner.rs b/reactive_graph/src/computed/inner.rs index 09da32b27..b076a0fed 100644 --- a/reactive_graph/src/computed/inner.rs +++ b/reactive_graph/src/computed/inner.rs @@ -6,7 +6,10 @@ use crate::{ owner::Owner, }; use or_poisoned::OrPoisoned; -use std::sync::{Arc, RwLock}; +use std::{ + fmt::Debug, + sync::{Arc, RwLock}, +}; pub struct MemoInner { pub(crate) value: Option, @@ -20,6 +23,12 @@ pub struct MemoInner { pub(crate) any_subscriber: AnySubscriber, } +impl Debug for MemoInner { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("MemoInner").finish_non_exhaustive() + } +} + impl MemoInner { #[allow(clippy::type_complexity)] pub fn new( diff --git a/reactive_graph/src/computed/memo.rs b/reactive_graph/src/computed/memo.rs index 9955b1e6d..0ae38ab0b 100644 --- a/reactive_graph/src/computed/memo.rs +++ b/reactive_graph/src/computed/memo.rs @@ -1,7 +1,7 @@ use super::{inner::MemoInner, ArcMemo}; use crate::{ owner::{Stored, StoredData}, - signal::MappedSignalReadGuard, + signal::guards::{Mapped, Plain, ReadGuard}, traits::{DefinedAt, ReadUntracked, Track}, }; use std::{fmt::Debug, panic::Location}; @@ -81,7 +81,7 @@ impl Track for Memo { } impl ReadUntracked for Memo { - type Value = MappedSignalReadGuard, T>; + type Value = ReadGuard>, T>>; fn try_read_untracked(&self) -> Option { self.get_value().map(|inner| inner.read_untracked()) diff --git a/reactive_graph/src/guards.rs b/reactive_graph/src/guards.rs deleted file mode 100644 index 05f42ac75..000000000 --- a/reactive_graph/src/guards.rs +++ /dev/null @@ -1 +0,0 @@ -pub struct SignalReadGuard<'a>(RwLockReadGuard<'a>); diff --git a/reactive_graph/src/lib.rs b/reactive_graph/src/lib.rs index 885d9d8a5..4b5749898 100644 --- a/reactive_graph/src/lib.rs +++ b/reactive_graph/src/lib.rs @@ -16,7 +16,7 @@ //! use reactive_graph::{ //! computed::ArcMemo, //! effect::Effect, -//! prelude::{Readable, Set}, +//! prelude::{Read, Set}, //! signal::ArcRwSignal, //! }; //! diff --git a/reactive_graph/src/signal.rs b/reactive_graph/src/signal.rs index 00355c922..85b827c20 100644 --- a/reactive_graph/src/signal.rs +++ b/reactive_graph/src/signal.rs @@ -1,7 +1,7 @@ mod arc_read; mod arc_rw; mod arc_write; -mod guards; +pub mod guards; mod read; mod rw; mod subscriber_traits; @@ -10,7 +10,6 @@ mod write; pub use arc_read::*; pub use arc_rw::*; pub use arc_write::*; -pub use guards::*; pub use read::*; pub use rw::*; pub use write::*; diff --git a/reactive_graph/src/signal/arc_read.rs b/reactive_graph/src/signal/arc_read.rs index 59c3bb3d9..e784c3cff 100644 --- a/reactive_graph/src/signal/arc_read.rs +++ b/reactive_graph/src/signal/arc_read.rs @@ -1,4 +1,7 @@ -use super::{subscriber_traits::AsSubscriberSet, SignalReadGuard}; +use super::{ + guards::{Plain, ReadGuard}, + subscriber_traits::AsSubscriberSet, +}; use crate::{ graph::SubscriberSet, traits::{DefinedAt, IsDisposed, ReadUntracked}, @@ -83,10 +86,10 @@ impl AsSubscriberSet for ArcReadSignal { } impl ReadUntracked for ArcReadSignal { - type Value = SignalReadGuard; + type Value = ReadGuard>; #[track_caller] fn try_read_untracked(&self) -> Option { - SignalReadGuard::try_new(Arc::clone(&self.value)) + Plain::try_new(Arc::clone(&self.value)).map(ReadGuard::new) } } diff --git a/reactive_graph/src/signal/arc_rw.rs b/reactive_graph/src/signal/arc_rw.rs index d91603496..07a94a8f6 100644 --- a/reactive_graph/src/signal/arc_rw.rs +++ b/reactive_graph/src/signal/arc_rw.rs @@ -1,6 +1,7 @@ use super::{ - subscriber_traits::AsSubscriberSet, ArcReadSignal, ArcWriteSignal, - SignalReadGuard, SignalUntrackedWriteGuard, SignalWriteGuard, + guards::{Plain, ReadGuard, UntrackedWriteGuard, WriteGuard}, + subscriber_traits::AsSubscriberSet, + ArcReadSignal, ArcWriteSignal, }; use crate::{ graph::{ReactiveNode, SubscriberSet}, @@ -113,10 +114,10 @@ impl AsSubscriberSet for ArcRwSignal { } impl ReadUntracked for ArcRwSignal { - type Value = SignalReadGuard; + type Value = ReadGuard>; fn try_read_untracked(&self) -> Option { - SignalReadGuard::try_new(Arc::clone(&self.value)) + Plain::try_new(Arc::clone(&self.value)).map(ReadGuard::new) } } @@ -129,16 +130,16 @@ impl Trigger for ArcRwSignal { impl Writeable for ArcRwSignal { type Value = T; - fn try_write(&self) -> Option> { + fn try_write(&self) -> Option> { self.value .write() .ok() - .map(|guard| SignalWriteGuard::new(self, guard)) + .map(|guard| WriteGuard::new(self, guard)) } fn try_write_untracked( &self, - ) -> Option> { - self.value.write().ok().map(SignalUntrackedWriteGuard::from) + ) -> Option> { + self.value.write().ok().map(UntrackedWriteGuard::from) } } diff --git a/reactive_graph/src/signal/arc_write.rs b/reactive_graph/src/signal/arc_write.rs index a6a31a801..1d03b3bbd 100644 --- a/reactive_graph/src/signal/arc_write.rs +++ b/reactive_graph/src/signal/arc_write.rs @@ -1,4 +1,4 @@ -use super::{SignalUntrackedWriteGuard, SignalWriteGuard}; +use super::guards::{UntrackedWriteGuard, WriteGuard}; use crate::{ graph::{ReactiveNode, SubscriberSet}, prelude::{IsDisposed, Trigger}, @@ -83,16 +83,16 @@ impl Trigger for ArcWriteSignal { impl Writeable for ArcWriteSignal { type Value = T; - fn try_write(&self) -> Option> { + fn try_write(&self) -> Option> { self.value .write() .ok() - .map(|guard| SignalWriteGuard::new(self, guard)) + .map(|guard| WriteGuard::new(self, guard)) } fn try_write_untracked( &self, - ) -> Option> { - self.value.write().ok().map(SignalUntrackedWriteGuard::from) + ) -> Option> { + self.value.write().ok().map(UntrackedWriteGuard::from) } } diff --git a/reactive_graph/src/signal/guards.rs b/reactive_graph/src/signal/guards.rs index f8310d650..20786ffdb 100644 --- a/reactive_graph/src/signal/guards.rs +++ b/reactive_graph/src/signal/guards.rs @@ -3,29 +3,76 @@ use core::fmt::Debug; use guardian::ArcRwLockReadGuardian; use std::{ fmt::Display, + marker::PhantomData, ops::{Deref, DerefMut}, sync::{Arc, RwLock, RwLockWriteGuard}, }; -pub struct SignalReadGuard { +#[derive(Debug)] +pub struct ReadGuard { + ty: PhantomData, + inner: Inner, +} + +impl ReadGuard { + pub fn new(inner: Inner) -> Self { + Self { + inner, + ty: PhantomData, + } + } +} + +impl Deref for ReadGuard +where + Inner: Deref, +{ + type Target = T; + + fn deref(&self) -> &Self::Target { + self.inner.deref() + } +} + +impl PartialEq for ReadGuard +where + Inner: Deref, + T: PartialEq, +{ + fn eq(&self, other: &Inner::Target) -> bool { + self.deref() == other + } +} + +impl Display for ReadGuard +where + Inner: Deref, + T: Display, +{ + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + Display::fmt(&**self, f) + } +} + +pub struct Plain { guard: ArcRwLockReadGuardian, } -impl Debug for SignalReadGuard { +impl Debug for Plain { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - f.debug_struct("SignalReadGuard").finish() + f.debug_struct("Plain").finish() } } -impl SignalReadGuard { - pub fn try_new(inner: Arc>) -> Option { +impl Plain { + pub(crate) fn try_new(inner: Arc>) -> Option { ArcRwLockReadGuardian::take(inner) .ok() - .map(|guard| SignalReadGuard { guard }) + .map(|guard| Plain { guard }) } } -impl Deref for SignalReadGuard { +impl Deref for Plain { type Target = T; fn deref(&self) -> &Self::Target { @@ -33,74 +80,92 @@ impl Deref for SignalReadGuard { } } -impl PartialEq for SignalReadGuard { +impl PartialEq for Plain { fn eq(&self, other: &Self) -> bool { **self == **other } } -impl PartialEq for SignalReadGuard { +impl PartialEq for Plain { fn eq(&self, other: &T) -> bool { **self == *other } } -impl Display for SignalReadGuard { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - Display::fmt(&**self, f) - } -} - -pub struct MappedSignalReadGuard { - guard: ArcRwLockReadGuardian, - map_fn: fn(&T) -> &U, -} - -impl Debug for MappedSignalReadGuard { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - f.debug_struct("MappedSignalReadGuard").finish() - } -} - -impl MappedSignalReadGuard { - pub fn try_new( - inner: Arc>, - map_fn: fn(&T) -> &U, - ) -> Option { - ArcRwLockReadGuardian::take(inner) - .ok() - .map(|guard| MappedSignalReadGuard { guard, map_fn }) - } -} - -impl Deref for MappedSignalReadGuard { - type Target = U; - - fn deref(&self) -> &Self::Target { - (self.map_fn)(self.guard.deref()) - } -} - -impl PartialEq for MappedSignalReadGuard { - fn eq(&self, other: &Self) -> bool { - **self == **other - } -} - -impl PartialEq for MappedSignalReadGuard { - fn eq(&self, other: &U) -> bool { - **self == *other - } -} - -impl Display for MappedSignalReadGuard { +impl Display for Plain { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { Display::fmt(&**self, f) } } #[derive(Debug)] -pub struct SignalWriteGuard<'a, S, T> +pub struct Mapped +where + Inner: Deref, +{ + inner: Inner, + map_fn: fn(&Inner::Target) -> &U, +} + +impl Mapped +where + Inner: Deref, +{ + pub(crate) fn new(inner: Inner, map_fn: fn(&Inner::Target) -> &U) -> Self { + Self { inner, map_fn } + } +} + +impl Mapped, U> { + pub(crate) fn try_new( + inner: Arc>, + map_fn: fn(&T) -> &U, + ) -> Option { + let inner = Plain::try_new(inner)?; + Some(Self { inner, map_fn }) + } +} + +impl Deref for Mapped +where + Inner: Deref, +{ + type Target = U; + + fn deref(&self) -> &Self::Target { + (self.map_fn)(self.inner.deref()) + } +} + +impl PartialEq for Mapped +where + Inner: Deref, +{ + fn eq(&self, other: &Self) -> bool { + **self == **other + } +} + +impl PartialEq for Mapped +where + Inner: Deref, +{ + fn eq(&self, other: &U) -> bool { + **self == *other + } +} + +impl Display for Mapped +where + Inner: Deref, +{ + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + Display::fmt(&**self, f) + } +} + +#[derive(Debug)] +pub struct WriteGuard<'a, S, T> where S: Trigger, { @@ -108,7 +173,7 @@ where guard: Option>, } -impl<'a, S, T> SignalWriteGuard<'a, S, T> +impl<'a, S, T> WriteGuard<'a, S, T> where S: Trigger, { @@ -120,7 +185,7 @@ where } } -impl<'a, S, T> Deref for SignalWriteGuard<'a, S, T> +impl<'a, S, T> Deref for WriteGuard<'a, S, T> where S: Trigger, { @@ -137,7 +202,7 @@ where } } -impl<'a, S, T> DerefMut for SignalWriteGuard<'a, S, T> +impl<'a, S, T> DerefMut for WriteGuard<'a, S, T> where S: Trigger, { @@ -153,15 +218,15 @@ where } #[derive(Debug)] -pub struct SignalUntrackedWriteGuard<'a, T>(RwLockWriteGuard<'a, T>); +pub struct UntrackedWriteGuard<'a, T>(RwLockWriteGuard<'a, T>); -impl<'a, T> From> for SignalUntrackedWriteGuard<'a, T> { +impl<'a, T> From> for UntrackedWriteGuard<'a, T> { fn from(value: RwLockWriteGuard<'a, T>) -> Self { Self(value) } } -impl<'a, T> Deref for SignalUntrackedWriteGuard<'a, T> { +impl<'a, T> Deref for UntrackedWriteGuard<'a, T> { type Target = T; fn deref(&self) -> &Self::Target { @@ -169,14 +234,14 @@ impl<'a, T> Deref for SignalUntrackedWriteGuard<'a, T> { } } -impl<'a, T> DerefMut for SignalUntrackedWriteGuard<'a, T> { +impl<'a, T> DerefMut for UntrackedWriteGuard<'a, T> { fn deref_mut(&mut self) -> &mut Self::Target { self.0.deref_mut() } } // Dropping the write guard will notify dependencies. -impl<'a, S, T> Drop for SignalWriteGuard<'a, S, T> +impl<'a, S, T> Drop for WriteGuard<'a, S, T> where S: Trigger, { diff --git a/reactive_graph/src/signal/read.rs b/reactive_graph/src/signal/read.rs index da8fa7ef5..ae1ee2ff9 100644 --- a/reactive_graph/src/signal/read.rs +++ b/reactive_graph/src/signal/read.rs @@ -1,5 +1,7 @@ use super::{ - subscriber_traits::AsSubscriberSet, ArcReadSignal, SignalReadGuard, + guards::{Plain, ReadGuard}, + subscriber_traits::AsSubscriberSet, + ArcReadSignal, }; use crate::{ graph::SubscriberSet, @@ -78,7 +80,7 @@ impl AsSubscriberSet for ReadSignal { } impl ReadUntracked for ReadSignal { - type Value = SignalReadGuard; + type Value = ReadGuard>; fn try_read_untracked(&self) -> Option { self.get_value().map(|inner| inner.read_untracked()) diff --git a/reactive_graph/src/signal/rw.rs b/reactive_graph/src/signal/rw.rs index f45d9f0f3..f6035ce7e 100644 --- a/reactive_graph/src/signal/rw.rs +++ b/reactive_graph/src/signal/rw.rs @@ -1,6 +1,7 @@ use super::{ - subscriber_traits::AsSubscriberSet, ArcRwSignal, ReadSignal, - SignalReadGuard, WriteSignal, + guards::{Plain, ReadGuard}, + subscriber_traits::AsSubscriberSet, + ArcRwSignal, ReadSignal, WriteSignal, }; use crate::{ graph::{ReactiveNode, SubscriberSet}, @@ -147,7 +148,7 @@ impl AsSubscriberSet for RwSignal { } impl ReadUntracked for RwSignal { - type Value = SignalReadGuard; + type Value = ReadGuard>; fn try_read_untracked(&self) -> Option { self.get_value().map(|inner| inner.read_untracked()) diff --git a/reactive_graph/src/traits.rs b/reactive_graph/src/traits.rs index 459c9c547..7080f9f62 100644 --- a/reactive_graph/src/traits.rs +++ b/reactive_graph/src/traits.rs @@ -50,7 +50,7 @@ use crate::{ graph::{Observer, Source, Subscriber, ToAnySource}, - signal::{SignalUntrackedWriteGuard, SignalWriteGuard}, + signal::guards::{UntrackedWriteGuard, WriteGuard}, }; use std::{ops::Deref, panic::Location}; @@ -138,17 +138,17 @@ where pub trait Writeable: Sized + DefinedAt + Trigger { type Value: Sized; - fn try_write(&self) -> Option>; + fn try_write(&self) -> Option>; fn try_write_untracked( &self, - ) -> Option>; + ) -> Option>; - fn write(&self) -> SignalWriteGuard<'_, Self, Self::Value> { + fn write(&self) -> WriteGuard<'_, Self, Self::Value> { self.try_write().unwrap_or_else(unwrap_signal!(self)) } - fn write_untracked(&self) -> SignalUntrackedWriteGuard<'_, Self::Value> { + fn write_untracked(&self) -> UntrackedWriteGuard<'_, Self::Value> { self.try_write_untracked() .unwrap_or_else(unwrap_signal!(self)) } diff --git a/reactive_graph/tests/async_derived.rs b/reactive_graph/tests/async_derived.rs index fa8ffd97e..9f474a630 100644 --- a/reactive_graph/tests/async_derived.rs +++ b/reactive_graph/tests/async_derived.rs @@ -5,7 +5,6 @@ use reactive_graph::{ traits::{Get, Read, Set, With, WithUntracked}, }; -#[cfg(feature = "tokio")] #[tokio::test] async fn arc_async_derived_calculates_eagerly() { use std::time::Duration; @@ -22,7 +21,6 @@ async fn arc_async_derived_calculates_eagerly() { std::mem::forget(value); } -#[cfg(feature = "tokio")] #[tokio::test] async fn arc_async_derived_tracks_signal_change() { use std::time::Duration; @@ -46,7 +44,6 @@ async fn arc_async_derived_tracks_signal_change() { std::mem::forget(value); } -#[cfg(feature = "tokio")] #[tokio::test] async fn async_derived_calculates_eagerly() { use std::time::Duration; @@ -62,7 +59,6 @@ async fn async_derived_calculates_eagerly() { assert_eq!(*value.await, 42); } -#[cfg(feature = "tokio")] #[tokio::test] async fn async_derived_tracks_signal_change() { use std::time::Duration; @@ -85,8 +81,10 @@ async fn async_derived_tracks_signal_change() { assert_eq!(value.await, 50); } -#[test] -fn read_signal_traits_on_arc() { +#[tokio::test] +async fn read_signal_traits_on_arc() { + _ = Executor::init_tokio(); + let value = ArcAsyncDerived::new(move || async {}); assert_eq!(value.read(), AsyncState::Loading); assert_eq!(value.with_untracked(|n| *n), AsyncState::Loading); @@ -94,8 +92,10 @@ fn read_signal_traits_on_arc() { assert_eq!(value.get(), AsyncState::Loading); } -#[test] -fn read_signal_traits_on_arena() { +#[tokio::test] +async fn read_signal_traits_on_arena() { + _ = Executor::init_tokio(); + let value = AsyncDerived::new(move || async {}); println!("{:?}", value.read()); assert_eq!(value.read(), AsyncState::Loading); diff --git a/reactive_graph/tests/effect.rs b/reactive_graph/tests/effect.rs index 5295e4317..c26d35607 100644 --- a/reactive_graph/tests/effect.rs +++ b/reactive_graph/tests/effect.rs @@ -13,10 +13,9 @@ pub async fn tick() { tokio::time::sleep(std::time::Duration::from_micros(1)).await; } -#[cfg(feature = "futures-executor")] -#[test] -fn render_effect_runs() { - _ = Executor::init_futures_executor(); +#[tokio::test] +async fn render_effect_runs() { + _ = Executor::init_tokio(); Executor::spawn(async { let a = RwSignal::new(-1); @@ -45,10 +44,9 @@ fn render_effect_runs() { }); } -#[cfg(feature = "futures-executor")] -#[test] -fn effect_runs() { - _ = Executor::init_futures_executor(); +#[tokio::test] +async fn effect_runs() { + _ = Executor::init_tokio(); Executor::spawn(async { let a = RwSignal::new(-1); @@ -74,10 +72,10 @@ fn effect_runs() { assert_eq!(b.read().unwrap().as_str(), "Value is 1"); }); } -#[cfg(feature = "futures-executor")] -#[test] -fn dynamic_dependencies() { - _ = Executor::init_futures_executor(); + +#[tokio::test] +async fn dynamic_dependencies() { + _ = Executor::init_tokio(); Executor::spawn(async { let first = RwSignal::new("Greg"); @@ -137,20 +135,3 @@ fn dynamic_dependencies() { assert_eq!(*combined_count.read().unwrap(), 5); }); } - -/* -#[cfg(feature = "futures-executor")] -#[test] -fn effect_runs() { - _ = Executor::init_futures_executor(); - - Executor::spawn(async {}); -} - -#[cfg(feature = "futures-executor")] -#[test] -fn effect_runs() { - _ = Executor::init_futures_executor(); - - Executor::spawn(async {}); -}*/ diff --git a/reactive_graph/tests/memo.rs b/reactive_graph/tests/memo.rs index c7a871c0c..4fcb923f1 100644 --- a/reactive_graph/tests/memo.rs +++ b/reactive_graph/tests/memo.rs @@ -169,10 +169,9 @@ fn diamond_problem() { assert_eq!(*combined_count.read().unwrap(), 1); } -#[cfg(feature = "tokio")] #[tokio::test] async fn dynamic_dependencies() { - _ = Executor::init_futures_executor(); + _ = Executor::init_tokio(); let first = RwSignal::new("Greg"); let last = RwSignal::new("Johnston"); diff --git a/tachys/src/reactive_graph/guards.rs b/tachys/src/reactive_graph/guards.rs index cf9c6e5c9..699fb3332 100644 --- a/tachys/src/reactive_graph/guards.rs +++ b/tachys/src/reactive_graph/guards.rs @@ -9,7 +9,7 @@ use crate::{ PositionState, Render, ToTemplate, }, }; -use reactive_graph::signal::SignalReadGuard; +use reactive_graph::signal::guards::ReadGuard; use std::{ fmt::Write, net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6}, @@ -18,6 +18,7 @@ use std::{ NonZeroIsize, NonZeroU128, NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU8, NonZeroUsize, }, + ops::Deref, }; // any changes here should also be made in src/view/primitives.rs @@ -26,9 +27,9 @@ macro_rules! render_primitive { ($($child_type:ty),* $(,)?) => { $( paste::paste! { - pub struct [](R::Text, $child_type) where R: Renderer; + pub struct [](R::Text, $child_type) where R: Renderer; - impl<'a, R: Renderer> Mountable for [] { + impl<'a, R: Renderer> Mountable for [] { fn unmount(&mut self) { self.0.unmount() } @@ -51,16 +52,18 @@ macro_rules! render_primitive { } } - impl<'a, R: Renderer> Render for SignalReadGuard<$child_type> { - type State = []; + impl<'a, G, R: Renderer> Render for ReadGuard<$child_type, G> + where G: Deref + { + type State = []; fn build(self) -> Self::State { let node = R::create_text_node(&self.to_string()); - [](node, *self) + [](node, *self) } fn rebuild(self, state: &mut Self::State) { - let [](node, this) = state; + let [](node, this) = state; if &self != this { R::set_text(node, &self.to_string()); *this = *self; @@ -68,13 +71,14 @@ macro_rules! render_primitive { } } - impl<'a> InfallibleRender for SignalReadGuard<$child_type> {} + impl<'a, G> InfallibleRender for ReadGuard<$child_type, G> {} - impl<'a, R> RenderHtml for SignalReadGuard<$child_type> + impl<'a, G, R> RenderHtml for ReadGuard<$child_type, G> where R: Renderer, R::Node: Clone, R::Element: Clone, + G: Deref { const MIN_LENGTH: usize = 0; @@ -112,11 +116,12 @@ macro_rules! render_primitive { } position.set(Position::NextChildAfterText); - [](node, *self) + [](node, *self) } } - impl<'a> ToTemplate for SignalReadGuard<$child_type> { + impl<'a, G> ToTemplate for ReadGuard<$child_type, G> + { const TEMPLATE: &'static str = " "; fn to_template( @@ -176,24 +181,27 @@ render_primitive![ ]; // strings -pub struct SignalReadGuardStringState { +pub struct ReadGuardStringState { node: R::Text, str: String, } -impl Render for SignalReadGuard { - type State = SignalReadGuardStringState; +impl Render for ReadGuard +where + G: Deref, +{ + type State = ReadGuardStringState; fn build(self) -> Self::State { let node = R::create_text_node(&self); - SignalReadGuardStringState { + ReadGuardStringState { node, str: self.to_string(), } } fn rebuild(self, state: &mut Self::State) { - let SignalReadGuardStringState { node, str } = state; + let ReadGuardStringState { node, str } = state; if *self != *str { R::set_text(node, &self); str.clear(); @@ -202,13 +210,14 @@ impl Render for SignalReadGuard { } } -impl InfallibleRender for SignalReadGuard {} +impl InfallibleRender for ReadGuard {} -impl RenderHtml for SignalReadGuard +impl RenderHtml for ReadGuard where R: Renderer, R::Node: Clone, R::Element: Clone, + G: Deref, { const MIN_LENGTH: usize = 0; @@ -224,14 +233,14 @@ where let this: &str = self.as_ref(); let StrState { node, .. } = this.hydrate::(cursor, position); - SignalReadGuardStringState { + ReadGuardStringState { node, str: self.to_string(), } } } -impl ToTemplate for SignalReadGuard { +impl ToTemplate for ReadGuard { const TEMPLATE: &'static str = <&str as ToTemplate>::TEMPLATE; fn to_template( @@ -247,7 +256,7 @@ impl ToTemplate for SignalReadGuard { } } -impl Mountable for SignalReadGuardStringState { +impl Mountable for ReadGuardStringState { fn unmount(&mut self) { self.node.unmount() }