Browse Source

clean up ref mapping with GATs

Evan Almloff 1 year ago
parent
commit
0a8de1d40f

+ 49 - 20
packages/generational-box/src/lib.rs

@@ -247,53 +247,82 @@ impl Default for SyncStorage {
     }
     }
 }
 }
 
 
-pub trait Mappable<T, U>: Deref<Target = T> {
-    type Mapped: Deref<Target = U>;
+pub trait Mappable<T>: Deref<Target = T> {
+    type Mapped<U: 'static>: Mappable<U> + Deref<Target = U>;
 
 
-    fn map(_self: Self, f: fn(&T) -> &U) -> Self::Mapped;
+    fn map<U: 'static>(_self: Self, f: fn(&T) -> &U) -> Self::Mapped<U>;
+
+    fn try_map<U: 'static>(_self: Self, f: fn(&T) -> Option<&U>) -> Option<Self::Mapped<U>>;
 }
 }
 
 
-impl<T, U: 'static> Mappable<T, U> for Ref<'static, T> {
-    type Mapped = Ref<'static, U>;
+impl<T> Mappable<T> for Ref<'static, T> {
+    type Mapped<U: 'static> = Ref<'static, U>;
 
 
-    fn map(_self: Self, f: fn(&T) -> &U) -> Self::Mapped {
+    fn map<U: 'static>(_self: Self, f: fn(&T) -> &U) -> Self::Mapped<U> {
         Ref::map(_self, f)
         Ref::map(_self, f)
     }
     }
+
+    fn try_map<U: 'static>(_self: Self, f: fn(&T) -> Option<&U>) -> Option<Self::Mapped<U>> {
+        Ref::try_map(_self, f)
+    }
 }
 }
 
 
-impl<T, U: 'static> Mappable<T, U> for MappedRwLockReadGuard<'static, T> {
-    type Mapped = MappedRwLockReadGuard<'static, U>;
+impl<T> Mappable<T> for MappedRwLockReadGuard<'static, T> {
+    type Mapped<U: 'static> = MappedRwLockReadGuard<'static, U>;
 
 
-    fn map(_self: Self, f: fn(&T) -> &U) -> Self::Mapped {
+    fn map<U: 'static>(_self: Self, f: fn(&T) -> &U) -> Self::Mapped<U> {
         MappedRwLockReadGuard::map(_self, f)
         MappedRwLockReadGuard::map(_self, f)
     }
     }
+
+    fn try_map<U: 'static>(_self: Self, f: fn(&T) -> Option<&U>) -> Option<Self::Mapped<U>> {
+        MappedRwLockReadGuard::try_map(_self, f).ok()
+    }
 }
 }
 
 
-pub trait MappableMut<T, U>: DerefMut<Target = T> {
-    type Mapped: DerefMut<Target = U>;
+pub trait MappableMut<T>: DerefMut<Target = T> {
+    type Mapped<U: 'static>: MappableMut<U> + DerefMut<Target = U>;
 
 
-    fn map(_self: Self, f: fn(&mut T) -> &mut U) -> Self::Mapped;
+    fn map<U: 'static>(_self: Self, f: impl FnOnce(&mut T) -> &mut U) -> Self::Mapped<U>;
+
+    fn try_map<U: 'static>(
+        _self: Self,
+        f: impl FnOnce(&mut T) -> Option<&mut U>,
+    ) -> Option<Self::Mapped<U>>;
 }
 }
 
 
-impl<T, U: 'static> MappableMut<T, U> for RefMut<'static, T> {
-    type Mapped = RefMut<'static, U>;
+impl<T> MappableMut<T> for RefMut<'static, T> {
+    type Mapped<U: 'static> = RefMut<'static, U>;
 
 
-    fn map(_self: Self, f: fn(&mut T) -> &mut U) -> Self::Mapped {
+    fn map<U: 'static>(_self: Self, f: impl FnOnce(&mut T) -> &mut U) -> Self::Mapped<U> {
         RefMut::map(_self, f)
         RefMut::map(_self, f)
     }
     }
+
+    fn try_map<U: 'static>(
+        _self: Self,
+        f: impl FnOnce(&mut T) -> Option<&mut U>,
+    ) -> Option<Self::Mapped<U>> {
+        RefMut::try_map(_self, f)
+    }
 }
 }
 
 
-impl<T, U: 'static> MappableMut<T, U> for MappedRwLockWriteGuard<'static, T> {
-    type Mapped = MappedRwLockWriteGuard<'static, U>;
+impl<T> MappableMut<T> for MappedRwLockWriteGuard<'static, T> {
+    type Mapped<U: 'static> = MappedRwLockWriteGuard<'static, U>;
 
 
-    fn map(_self: Self, f: fn(&mut T) -> &mut U) -> Self::Mapped {
+    fn map<U: 'static>(_self: Self, f: impl FnOnce(&mut T) -> &mut U) -> Self::Mapped<U> {
         MappedRwLockWriteGuard::map(_self, f)
         MappedRwLockWriteGuard::map(_self, f)
     }
     }
+
+    fn try_map<U: 'static>(
+        _self: Self,
+        f: impl FnOnce(&mut T) -> Option<&mut U>,
+    ) -> Option<Self::Mapped<U>> {
+        MappedRwLockWriteGuard::try_map(_self, f).ok()
+    }
 }
 }
 
 
 pub trait Storage<Data>: Copy + AnyStorage {
 pub trait Storage<Data>: Copy + AnyStorage {
-    type Ref: Deref<Target = Data>;
-    type Mut: DerefMut<Target = Data>;
+    type Ref: Mappable<Data> + Deref<Target = Data>;
+    type Mut: MappableMut<Data> + DerefMut<Target = Data>;
 
 
     fn try_read(&self) -> Option<Self::Ref>;
     fn try_read(&self) -> Option<Self::Ref>;
     fn read(&self) -> Self::Ref {
     fn read(&self) -> Self::Ref {

+ 4 - 5
packages/signals/src/effect.rs

@@ -1,15 +1,14 @@
 use core::{self, fmt::Debug};
 use core::{self, fmt::Debug};
-use std::fmt::{self, Formatter};
-//
 use dioxus_core::prelude::*;
 use dioxus_core::prelude::*;
-use generational_box::SyncStorage;
+use generational_box::UnsyncStorage;
+use std::fmt::{self, Formatter};
 
 
 use crate::use_signal;
 use crate::use_signal;
 use crate::{dependency::Dependency, CopyValue};
 use crate::{dependency::Dependency, CopyValue};
 
 
 #[derive(Copy, Clone, PartialEq)]
 #[derive(Copy, Clone, PartialEq)]
 pub(crate) struct EffectStack {
 pub(crate) struct EffectStack {
-    pub(crate) effects: CopyValue<Vec<Effect>, SyncStorage>,
+    pub(crate) effects: CopyValue<Vec<Effect>, UnsyncStorage>,
 }
 }
 
 
 impl Default for EffectStack {
 impl Default for EffectStack {
@@ -69,7 +68,7 @@ pub fn use_effect_with_dependencies<D: Dependency>(
 #[derive(Copy, Clone, PartialEq)]
 #[derive(Copy, Clone, PartialEq)]
 pub struct Effect {
 pub struct Effect {
     pub(crate) source: ScopeId,
     pub(crate) source: ScopeId,
-    pub(crate) callback: CopyValue<Box<dyn FnMut()>, SyncStorage>,
+    pub(crate) callback: CopyValue<Box<dyn FnMut()>, UnsyncStorage>,
     pub(crate) effect_stack: EffectStack,
     pub(crate) effect_stack: EffectStack,
 }
 }
 
 

+ 58 - 42
packages/signals/src/impls.rs

@@ -1,6 +1,7 @@
 use crate::rt::CopyValue;
 use crate::rt::CopyValue;
 use crate::signal::{ReadOnlySignal, Signal, Write};
 use crate::signal::{ReadOnlySignal, Signal, Write};
 use crate::SignalData;
 use crate::SignalData;
+use generational_box::Mappable;
 use generational_box::{MappableMut, Storage};
 use generational_box::{MappableMut, Storage};
 use parking_lot::{MappedRwLockReadGuard, MappedRwLockWriteGuard};
 use parking_lot::{MappedRwLockReadGuard, MappedRwLockWriteGuard};
 
 
@@ -11,40 +12,40 @@ use std::{
 
 
 macro_rules! read_impls {
 macro_rules! read_impls {
     ($ty:ident) => {
     ($ty:ident) => {
-        impl<T: Default + 'static> Default for $ty<T> {
+        impl<T: Default + 'static, S: Storage<T>> Default for $ty<T, S> {
             fn default() -> Self {
             fn default() -> Self {
                 Self::new(Default::default())
                 Self::new(Default::default())
             }
             }
         }
         }
 
 
-        impl<T> std::clone::Clone for $ty<T> {
+        impl<T, S: Storage<T>> std::clone::Clone for $ty<T, S> {
             fn clone(&self) -> Self {
             fn clone(&self) -> Self {
                 *self
                 *self
             }
             }
         }
         }
 
 
-        impl<T> Copy for $ty<T> {}
+        impl<T, S: Storage<T> + Copy> Copy for $ty<T, S> {}
 
 
-        impl<T: Display + 'static> Display for $ty<T> {
+        impl<T: Display + 'static, S: Storage<T>> Display for $ty<T, S> {
             fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
             fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
                 self.with(|v| Display::fmt(v, f))
                 self.with(|v| Display::fmt(v, f))
             }
             }
         }
         }
 
 
-        impl<T: Debug + 'static> Debug for $ty<T> {
+        impl<T: Debug + 'static, S: Storage<T>> Debug for $ty<T, S> {
             fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
             fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
                 self.with(|v| Debug::fmt(v, f))
                 self.with(|v| Debug::fmt(v, f))
             }
             }
         }
         }
 
 
-        impl<T: 'static> $ty<Vec<T>> {
+        impl<T: 'static, S: Storage<T>> $ty<Vec<T>, S> {
             /// Read a value from the inner vector.
             /// Read a value from the inner vector.
             pub fn get(&self, index: usize) -> Option<MappedRwLockReadGuard<'static, T>> {
             pub fn get(&self, index: usize) -> Option<MappedRwLockReadGuard<'static, T>> {
                 MappedRwLockReadGuard::try_map(self.read(), |v| v.get(index)).ok()
                 MappedRwLockReadGuard::try_map(self.read(), |v| v.get(index)).ok()
             }
             }
         }
         }
 
 
-        impl<T: 'static> $ty<Option<T>> {
+        impl<T: 'static, S: Storage<T>> $ty<Option<T>, S> {
             /// Unwraps the inner value and clones it.
             /// Unwraps the inner value and clones it.
             pub fn unwrap(&self) -> T
             pub fn unwrap(&self) -> T
             where
             where
@@ -63,7 +64,7 @@ macro_rules! read_impls {
 
 
 macro_rules! write_impls {
 macro_rules! write_impls {
     ($ty:ident) => {
     ($ty:ident) => {
-        impl<T: Add<Output = T> + Copy + 'static> std::ops::Add<T> for $ty<T> {
+        impl<T: Add<Output = T> + Copy + 'static, S: Storage<T>> std::ops::Add<T> for $ty<T, S> {
             type Output = T;
             type Output = T;
 
 
             fn add(self, rhs: T) -> Self::Output {
             fn add(self, rhs: T) -> Self::Output {
@@ -71,19 +72,23 @@ macro_rules! write_impls {
             }
             }
         }
         }
 
 
-        impl<T: Add<Output = T> + Copy + 'static> std::ops::AddAssign<T> for $ty<T> {
+        impl<T: Add<Output = T> + Copy + 'static, S: Storage<T>> std::ops::AddAssign<T>
+            for $ty<T, S>
+        {
             fn add_assign(&mut self, rhs: T) {
             fn add_assign(&mut self, rhs: T) {
                 self.with_mut(|v| *v = *v + rhs)
                 self.with_mut(|v| *v = *v + rhs)
             }
             }
         }
         }
 
 
-        impl<T: Sub<Output = T> + Copy + 'static> std::ops::SubAssign<T> for $ty<T> {
+        impl<T: Sub<Output = T> + Copy + 'static, S: Storage<T>> std::ops::SubAssign<T>
+            for $ty<T, S>
+        {
             fn sub_assign(&mut self, rhs: T) {
             fn sub_assign(&mut self, rhs: T) {
                 self.with_mut(|v| *v = *v - rhs)
                 self.with_mut(|v| *v = *v - rhs)
             }
             }
         }
         }
 
 
-        impl<T: Sub<Output = T> + Copy + 'static> std::ops::Sub<T> for $ty<T> {
+        impl<T: Sub<Output = T> + Copy + 'static, S: Storage<T>> std::ops::Sub<T> for $ty<T, S> {
             type Output = T;
             type Output = T;
 
 
             fn sub(self, rhs: T) -> Self::Output {
             fn sub(self, rhs: T) -> Self::Output {
@@ -91,13 +96,15 @@ macro_rules! write_impls {
             }
             }
         }
         }
 
 
-        impl<T: Mul<Output = T> + Copy + 'static> std::ops::MulAssign<T> for $ty<T> {
+        impl<T: Mul<Output = T> + Copy + 'static, S: Storage<T>> std::ops::MulAssign<T>
+            for $ty<T, S>
+        {
             fn mul_assign(&mut self, rhs: T) {
             fn mul_assign(&mut self, rhs: T) {
                 self.with_mut(|v| *v = *v * rhs)
                 self.with_mut(|v| *v = *v * rhs)
             }
             }
         }
         }
 
 
-        impl<T: Mul<Output = T> + Copy + 'static> std::ops::Mul<T> for $ty<T> {
+        impl<T: Mul<Output = T> + Copy + 'static, S: Storage<T>> std::ops::Mul<T> for $ty<T, S> {
             type Output = T;
             type Output = T;
 
 
             fn mul(self, rhs: T) -> Self::Output {
             fn mul(self, rhs: T) -> Self::Output {
@@ -105,13 +112,15 @@ macro_rules! write_impls {
             }
             }
         }
         }
 
 
-        impl<T: Div<Output = T> + Copy + 'static> std::ops::DivAssign<T> for $ty<T> {
+        impl<T: Div<Output = T> + Copy + 'static, S: Storage<T>> std::ops::DivAssign<T>
+            for $ty<T, S>
+        {
             fn div_assign(&mut self, rhs: T) {
             fn div_assign(&mut self, rhs: T) {
                 self.with_mut(|v| *v = *v / rhs)
                 self.with_mut(|v| *v = *v / rhs)
             }
             }
         }
         }
 
 
-        impl<T: Div<Output = T> + Copy + 'static> std::ops::Div<T> for $ty<T> {
+        impl<T: Div<Output = T> + Copy + 'static, S: Storage<T>> std::ops::Div<T> for $ty<T, S> {
             type Output = T;
             type Output = T;
 
 
             fn div(self, rhs: T) -> Self::Output {
             fn div(self, rhs: T) -> Self::Output {
@@ -119,7 +128,7 @@ macro_rules! write_impls {
             }
             }
         }
         }
 
 
-        impl<T: 'static> $ty<Vec<T>> {
+        impl<T: 'static, S: Storage<T>> $ty<Vec<T>, S> {
             /// Pushes a new value to the end of the vector.
             /// Pushes a new value to the end of the vector.
             pub fn push(&self, value: T) {
             pub fn push(&self, value: T) {
                 self.with_mut(|v| v.push(value))
                 self.with_mut(|v| v.push(value))
@@ -171,7 +180,7 @@ macro_rules! write_impls {
             }
             }
         }
         }
 
 
-        impl<T: 'static> $ty<Option<T>> {
+        impl<T: 'static, S: Storage<T>> $ty<Option<T>, S> {
             /// Takes the value out of the Option.
             /// Takes the value out of the Option.
             pub fn take(&self) -> Option<T> {
             pub fn take(&self) -> Option<T> {
                 self.with_mut(|v| v.take())
                 self.with_mut(|v| v.take())
@@ -183,7 +192,7 @@ macro_rules! write_impls {
             }
             }
 
 
             /// Gets the value out of the Option, or inserts the given value if the Option is empty.
             /// 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) -> MappedRwLockReadGuard<'_, T> {
+            pub fn get_or_insert(&self, default: T) -> S::Ref {
                 self.get_or_insert_with(|| default)
                 self.get_or_insert_with(|| default)
             }
             }
 
 
@@ -191,25 +200,25 @@ macro_rules! write_impls {
             pub fn get_or_insert_with(
             pub fn get_or_insert_with(
                 &self,
                 &self,
                 default: impl FnOnce() -> T,
                 default: impl FnOnce() -> T,
-            ) -> MappedRwLockReadGuard<'_, T> {
+            ) -> <S::Ref as Mappable<T>>::Mapped<T> {
                 let borrow = self.read();
                 let borrow = self.read();
                 if borrow.is_none() {
                 if borrow.is_none() {
                     drop(borrow);
                     drop(borrow);
                     self.with_mut(|v| *v = Some(default()));
                     self.with_mut(|v| *v = Some(default()));
-                    MappedRwLockReadGuard::map(self.read(), |v| v.as_ref().unwrap())
+                    S::Ref::map(self.read(), |v| v.as_ref().unwrap())
                 } else {
                 } else {
-                    MappedRwLockReadGuard::map(borrow, |v| v.as_ref().unwrap())
+                    S::Ref::map(borrow, |v| v.as_ref().unwrap())
                 }
                 }
             }
             }
         }
         }
     };
     };
 }
 }
 
 
-// read_impls!(CopyValue);
-// write_impls!(CopyValue);
-// read_impls!(Signal);
-// write_impls!(Signal);
-// read_impls!(ReadOnlySignal);
+read_impls!(CopyValue);
+write_impls!(CopyValue);
+read_impls!(Signal);
+write_impls!(Signal);
+read_impls!(ReadOnlySignal);
 
 
 /// An iterator over the values of a `CopyValue<Vec<T>>`.
 /// An iterator over the values of a `CopyValue<Vec<T>>`.
 pub struct CopyValueIterator<T: 'static, S: Storage<T>> {
 pub struct CopyValueIterator<T: 'static, S: Storage<T>> {
@@ -240,23 +249,19 @@ impl<T: Clone + 'static, S: Storage<T>> IntoIterator for CopyValue<Vec<T>, S> {
     }
     }
 }
 }
 
 
-impl<T: 'static, S: Storage<Vec<T>>> CopyValue<Vec<T>, S>
-where
-    <S as Storage<Vec<T>>>::Mut: MappableMut<Vec<T>, T>,
-{
+impl<T: 'static, S: Storage<Vec<T>>> CopyValue<Vec<T>, S> {
     /// Write to an element in the inner vector.
     /// Write to an element in the inner vector.
-    pub fn get_mut(&self, index: usize) -> Option<<S::Mut as MappableMut<Vec<T>, T>>::Mapped> {
-        MappedRwLockWriteGuard::try_map(self.write(), |v| v.get_mut(index)).ok()
+    pub fn get_mut(&self, index: usize) -> Option<<S::Mut as MappableMut<Vec<T>>>::Mapped<T>> {
+        S::Mut::try_map(self.write(), |v: &mut Vec<T>| v.get_mut(index))
     }
     }
 }
 }
 
 
-impl<T: 'static, S: Storage<Option<T>>> CopyValue<Option<T>, S>
-where
-    <S as Storage<Option<T>>>::Mut: MappableMut<Option<T>, T>,
-{
+impl<T: 'static, S: Storage<Option<T>>> CopyValue<Option<T>, S> {
     /// Deref the inner value mutably.
     /// Deref the inner value mutably.
-    pub fn as_mut(&self) -> Option<<S::Mut as MappableMut<Option<T>, T>>::Mapped> {
-        S::Mut::map(self.try_write(), |v| v.as_mut()).ok()
+    pub fn as_mut(
+        &self,
+    ) -> Option<<<S as Storage<Option<T>>>::Mut as MappableMut<Option<T>>>::Mapped<T>> {
+        S::Mut::try_map(self.write(), |v: &mut Option<T>| v.as_mut())
     }
     }
 }
 }
 
 
@@ -291,20 +296,31 @@ impl<T: Clone + 'static, S: Storage<T>> IntoIterator for Signal<Vec<T>, S> {
 
 
 impl<T: 'static, S: Storage<SignalData<Vec<T>>>> Signal<Vec<T>, S>
 impl<T: 'static, S: Storage<SignalData<Vec<T>>>> Signal<Vec<T>, S>
 where
 where
-    S::Mut: MappableMut<Vec<T>, T>,
+    <<S as Storage<SignalData<std::vec::Vec<T>>>>::Mut as MappableMut<
+        SignalData<std::vec::Vec<T>>,
+    >>::Mapped<std::vec::Vec<T>>: MappableMut<std::vec::Vec<T>>,
 {
 {
     /// Returns a reference to an element or `None` if out of bounds.
     /// Returns a reference to an element or `None` if out of bounds.
     pub fn get_mut(
     pub fn get_mut(
         &self,
         &self,
         index: usize,
         index: usize,
-    ) -> Option<Write<T, <S::Mut as MappableMut<Vec<T>, T>>::Mapped, S, Vec<T>>> {
-        S::Mut::map(self.write(), |v| v.get_mut(index))
+    ) -> Option<
+        Write<
+            T,
+            <<<S as Storage<SignalData<Vec<T>>>>::Mut as MappableMut<SignalData<Vec<T>>>>::Mapped<
+                Vec<T>,
+            > as MappableMut<Vec<T>>>::Mapped<T>,
+            S,
+            Vec<T>,
+        >,
+    > {
+        Write::filter_map(self.write(), |v| v.get_mut(index))
     }
     }
 }
 }
 
 
 impl<T: 'static, S: Storage<SignalData<Option<T>>>> Signal<Option<T>, S> {
 impl<T: 'static, S: Storage<SignalData<Option<T>>>> Signal<Option<T>, S> {
     /// Returns a reference to an element or `None` if out of bounds.
     /// Returns a reference to an element or `None` if out of bounds.
-    pub fn as_mut(&self) -> Option<Write<SignalData<Option<T>>, S::Mut, S, Option<T>>> {
+    pub fn as_mut(&self) -> Option<Write<T, <<<S as Storage<SignalData<Option<T>>>>::Mut as MappableMut<SignalData<Option<T>>>>::Mapped<Option<T>> as MappableMut<Option<T>>>::Mapped<T>, S, Option<T>>>{
         Write::filter_map(self.write(), |v| v.as_mut())
         Write::filter_map(self.write(), |v| v.as_mut())
     }
     }
 }
 }

+ 26 - 31
packages/signals/src/rt.rs

@@ -11,32 +11,34 @@ use generational_box::{GenerationalBox, Owner};
 
 
 use crate::Effect;
 use crate::Effect;
 
 
-fn current_owner() -> Rc<Owner> {
-    match Effect::current() {
-        // If we are inside of an effect, we should use the owner of the effect as the owner of the value.
-        Some(effect) => {
-            let scope_id = effect.source;
-            owner_in_scope(scope_id)
-        }
-        // Otherwise either get an owner from the current scope or create a new one.
-        None => match has_context() {
-            Some(rt) => rt,
-            None => {
-                let owner = Rc::new(current_store().owner());
-                provide_context(owner).expect("in a virtual dom")
-            }
-        },
-    }
+fn current_owner<S: Storage<T>, T>() -> Rc<Owner<S>> {
+    todo!()
+    // match Effect::current() {
+    //     // If we are inside of an effect, we should use the owner of the effect as the owner of the value.
+    //     Some(effect) => {
+    //         let scope_id = effect.source;
+    //         owner_in_scope(scope_id)
+    //     }
+    //     // Otherwise either get an owner from the current scope or create a new one.
+    //     None => match has_context() {
+    //         Some(rt) => rt,
+    //         None => {
+    //             let owner = Rc::new(current_store().owner());
+    //             provide_context(owner).expect("in a virtual dom")
+    //         }
+    //     },
+    // }
 }
 }
 
 
-fn owner_in_scope(scope: ScopeId) -> Rc<Owner> {
-    match consume_context_from_scope(scope) {
-        Some(rt) => rt,
-        None => {
-            let owner = Rc::new(current_store().owner());
-            provide_context_to_scope(scope, owner).expect("in a virtual dom")
-        }
-    }
+fn owner_in_scope<S: Storage<T>, T>(scope: ScopeId) -> Rc<Owner<S>> {
+    todo!()
+    // match consume_context_from_scope(scope) {
+    //     Some(rt) => rt,
+    //     None => {
+    //         let owner = Rc::new(current_store().owner());
+    //         provide_context_to_scope(scope, owner).expect("in a virtual dom")
+    //     }
+    // }
 }
 }
 
 
 #[derive(Debug)]
 #[derive(Debug)]
@@ -48,13 +50,6 @@ pub struct CopyValue<T: 'static, S: AnyStorage> {
     origin_scope: ScopeId,
     origin_scope: ScopeId,
 }
 }
 
 
-impl<T: 'static, S: AnyStorage + Copy> Copy for CopyValue<T, S> {}
-impl<T: 'static, S: AnyStorage + Clone> Clone for CopyValue<T, S> {
-    fn clone(&self) -> Self {
-        *self
-    }
-}
-
 #[cfg(feature = "serde")]
 #[cfg(feature = "serde")]
 impl<T: 'static> serde::Serialize for CopyValue<T>
 impl<T: 'static> serde::Serialize for CopyValue<T>
 where
 where

+ 1 - 2
packages/signals/src/selector.rs

@@ -75,7 +75,7 @@ where
 pub fn selector<R: PartialEq, S: Storage<SignalData<R>>>(
 pub fn selector<R: PartialEq, S: Storage<SignalData<R>>>(
     mut f: impl FnMut() -> R + 'static,
     mut f: impl FnMut() -> R + 'static,
 ) -> ReadOnlySignal<R, S> {
 ) -> ReadOnlySignal<R, S> {
-    let state = Signal::<R> {
+    let state = Signal::<R, S> {
         inner: CopyValue::invalid(),
         inner: CopyValue::invalid(),
     };
     };
     let effect = Effect {
     let effect = Effect {
@@ -89,7 +89,6 @@ pub fn selector<R: PartialEq, S: Storage<SignalData<R>>>(
     }
     }
     state.inner.value.set(SignalData {
     state.inner.value.set(SignalData {
         subscribers: Default::default(),
         subscribers: Default::default(),
-        effect_subscribers: Default::default(),
         update_any: schedule_update_any().expect("in a virtual dom"),
         update_any: schedule_update_any().expect("in a virtual dom"),
         value: f(),
         value: f(),
         effect_stack: get_effect_stack(),
         effect_stack: get_effect_stack(),

+ 101 - 44
packages/signals/src/signal.rs

@@ -1,5 +1,6 @@
 use std::{
 use std::{
     cell::RefCell,
     cell::RefCell,
+    marker::PhantomData,
     mem::MaybeUninit,
     mem::MaybeUninit,
     ops::{Deref, DerefMut},
     ops::{Deref, DerefMut},
     rc::Rc,
     rc::Rc,
@@ -10,8 +11,8 @@ 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};
-use parking_lot::{MappedRwLockReadGuard, MappedRwLockWriteGuard};
+use generational_box::{AnyStorage, Mappable, MappableMut, Storage, SyncStorage, UnsyncStorage};
+use parking_lot::RwLock;
 
 
 use crate::{get_effect_stack, CopyValue, Effect, EffectStack};
 use crate::{get_effect_stack, CopyValue, Effect, EffectStack};
 
 
@@ -47,11 +48,51 @@ use crate::{get_effect_stack, CopyValue, Effect, EffectStack};
 /// }
 /// }
 /// ```
 /// ```
 #[must_use]
 #[must_use]
-pub fn use_signal<T: 'static, S: Storage<SignalData<T>>>(
+pub fn use_signal<T: 'static>(cx: &ScopeState, f: impl FnOnce() -> T) -> Signal<T, UnsyncStorage> {
+    *cx.use_hook(|| Signal::new(f()))
+}
+
+/// Creates a new `Send + Sync`` Signal. Signals are a Copy state management solution with automatic dependency tracking.
+///
+/// ```rust
+/// use dioxus::prelude::*;
+/// use dioxus_signals::*;
+///
+/// fn App(cx: Scope) -> Element {
+///     let mut count = use_signal(cx, || 0);
+///
+///     // Because signals have automatic dependency tracking, if you never read them in a component, that component will not be re-rended when the signal is updated.
+///     // The app component will never be rerendered in this example.
+///     render! { Child { state: count } }
+/// }
+///
+/// #[component]
+/// fn Child(cx: Scope, state: Signal<u32>) -> Element {
+///     let state = *state;
+///
+///     use_future!(cx,  |()| async move {
+///         // This signal is Send + Sync, so we can use it in an another thread
+///         tokio::spawn(async move {
+///             // Because the signal is a Copy type, we can use it in an async block without cloning it.
+///             *state.write() += 1;
+///         }).await;
+///     });
+///
+///     render! {
+///         button {
+///             onclick: move |_| *state.write() += 1,
+///             "{state}"
+///         }
+///     }
+/// }
+/// ```
+#[must_use]
+pub fn use_signal_sync<T: Send + Sync + 'static>(
     cx: &ScopeState,
     cx: &ScopeState,
     f: impl FnOnce() -> T,
     f: impl FnOnce() -> T,
-) -> Signal<T, S> {
-    *cx.use_hook(|| Signal::new(f()))
+) -> Signal<T, SyncStorage> {
+    // *cx.use_hook(|| Signal::new(f()))
+    todo!()
 }
 }
 
 
 #[derive(Clone)]
 #[derive(Clone)]
@@ -83,10 +124,15 @@ fn current_unsubscriber() -> Unsubscriber {
     }
     }
 }
 }
 
 
+#[derive(Default)]
+pub(crate) struct SignalSubscribers {
+    pub(crate) subscribers: Vec<ScopeId>,
+    pub(crate) effect_subscribers: Vec<Effect>,
+}
+
 pub(crate) struct SignalData<T> {
 pub(crate) struct SignalData<T> {
-    pub(crate) subscribers: Rc<RefCell<Vec<ScopeId>>>,
-    pub(crate) effect_subscribers: Rc<RefCell<Vec<Effect>>>,
-    pub(crate) update_any: Arc<dyn Fn(ScopeId)>,
+    pub(crate) subscribers: Arc<RwLock<SignalSubscribers>>,
+    pub(crate) update_any: Arc<dyn Fn(ScopeId) + Sync + Send>,
     pub(crate) effect_stack: EffectStack,
     pub(crate) effect_stack: EffectStack,
     pub(crate) value: T,
     pub(crate) value: T,
 }
 }
@@ -123,7 +169,7 @@ pub(crate) struct SignalData<T> {
 ///     }
 ///     }
 /// }
 /// }
 /// ```
 /// ```
-pub struct Signal<T: 'static, S: AnyStorage> {
+pub struct Signal<T: 'static, S: Storage<SignalData<T>>> {
     pub(crate) inner: CopyValue<SignalData<T>, S>,
     pub(crate) inner: CopyValue<SignalData<T>, S>,
 }
 }
 
 
@@ -147,7 +193,6 @@ impl<T: 'static, S: Storage<SignalData<T>>> Signal<T, S> {
         Self {
         Self {
             inner: CopyValue::new(SignalData {
             inner: CopyValue::new(SignalData {
                 subscribers: Default::default(),
                 subscribers: Default::default(),
-                effect_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_stack: get_effect_stack(),
@@ -161,7 +206,6 @@ impl<T: 'static, S: Storage<SignalData<T>>> Signal<T, S> {
             inner: CopyValue::new_in_scope(
             inner: CopyValue::new_in_scope(
                 SignalData {
                 SignalData {
                     subscribers: Default::default(),
                     subscribers: Default::default(),
-                    effect_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_stack: get_effect_stack(),
@@ -178,13 +222,13 @@ impl<T: 'static, S: Storage<SignalData<T>>> Signal<T, S> {
 
 
     /// Get the current value of the signal. This will subscribe the current scope to the signal.
     /// Get the current value of the signal. This will subscribe the current scope to the signal.
     /// If the signal has been dropped, this will panic.
     /// If the signal has been dropped, this will panic.
-    pub fn read(&self) -> <<S as Storage<SignalData<T>>>::Ref as Mappable<SignalData<T>, T>>::Mapped
-    where
-        <S as Storage<SignalData<T>>>::Ref: Mappable<SignalData<T>, T>,
-    {
+    pub fn read(
+        &self,
+    ) -> <<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) = inner.effect_stack.current() {
-            let mut effect_subscribers = inner.effect_subscribers.borrow_mut();
+            let mut subscribers = inner.subscribers.write();
+            let mut effect_subscribers = &mut subscribers.effect_subscribers;
             if !effect_subscribers.contains(&effect) {
             if !effect_subscribers.contains(&effect) {
                 effect_subscribers.push(effect);
                 effect_subscribers.push(effect);
             }
             }
@@ -196,12 +240,17 @@ impl<T: 'static, S: Storage<SignalData<T>>> Signal<T, S> {
                     self.inner.value,
                     self.inner.value,
                     current_scope_id
                     current_scope_id
                 );
                 );
-                let mut subscribers = inner.subscribers.borrow_mut();
+                let mut subscribers = inner.subscribers.write();
+                let subscribers = &mut subscribers.subscribers;
                 if !subscribers.contains(&current_scope_id) {
                 if !subscribers.contains(&current_scope_id) {
                     subscribers.push(current_scope_id);
                     subscribers.push(current_scope_id);
                     drop(subscribers);
                     drop(subscribers);
                     let unsubscriber = current_unsubscriber();
                     let unsubscriber = current_unsubscriber();
-                    inner.subscribers.borrow_mut().push(unsubscriber.scope);
+                    inner
+                        .subscribers
+                        .write()
+                        .subscribers
+                        .push(unsubscriber.scope);
                 }
                 }
             }
             }
         }
         }
@@ -212,22 +261,21 @@ impl<T: 'static, S: Storage<SignalData<T>>> Signal<T, S> {
     /// If the signal has been dropped, this will panic.
     /// If the signal has been dropped, this will panic.
     pub fn write(
     pub fn write(
         &self,
         &self,
-    ) -> Write<T, <<S as Storage<SignalData<T>>>::Mut as MappableMut<SignalData<T>, T>>::Mapped, S>
-    where
-        <S as Storage<SignalData<T>>>::Mut: MappableMut<SignalData<T>, T>,
+    ) -> Write<T, <<S as Storage<SignalData<T>>>::Mut as MappableMut<SignalData<T>>>::Mapped<T>, S>
     {
     {
         let inner = self.inner.write();
         let inner = self.inner.write();
         let borrow = S::Mut::map(inner, |v| &mut v.value);
         let borrow = S::Mut::map(inner, |v| &mut v.value);
         Write {
         Write {
             write: borrow,
             write: borrow,
             signal: SignalSubscriberDrop { signal: *self },
             signal: SignalSubscriberDrop { signal: *self },
+            phantom: std::marker::PhantomData,
         }
         }
     }
     }
 
 
     fn update_subscribers(&self) {
     fn update_subscribers(&self) {
         {
         {
             let inner = self.inner.read();
             let inner = self.inner.read();
-            for &scope_id in &*inner.subscribers.borrow() {
+            for &scope_id in &*inner.subscribers.read().subscribers {
                 tracing::trace!(
                 tracing::trace!(
                     "Write on {:?} triggered update on {:?}",
                     "Write on {:?} triggered update on {:?}",
                     self.inner.value,
                     self.inner.value,
@@ -239,7 +287,7 @@ impl<T: 'static, S: Storage<SignalData<T>>> Signal<T, S> {
 
 
         let subscribers = {
         let subscribers = {
             let self_read = self.inner.read();
             let self_read = self.inner.read();
-            let mut effects = self_read.effect_subscribers.borrow_mut();
+            let mut effects = &mut self_read.subscribers.write().effect_subscribers;
             std::mem::take(&mut *effects)
             std::mem::take(&mut *effects)
         };
         };
         for effect in subscribers {
         for effect in subscribers {
@@ -280,7 +328,7 @@ impl<T: Clone + 'static, S: Storage<SignalData<T>>> Signal<T, S> {
     }
     }
 }
 }
 
 
-impl<S: Storage<bool>> Signal<bool, S> {
+impl<S: Storage<SignalData<bool>>> Signal<bool, S> {
     /// Invert the boolean value of the signal. This will trigger an update on all subscribers.
     /// Invert the boolean value of the signal. This will trigger an update on all subscribers.
     pub fn toggle(&self) {
     pub fn toggle(&self) {
         self.set(!self.value());
         self.set(!self.value());
@@ -294,7 +342,8 @@ impl<T: 'static, S: Storage<SignalData<T>>> PartialEq for Signal<T, S> {
 }
 }
 
 
 impl<T, S: Storage<SignalData<T>>> Deref for Signal<T, S> {
 impl<T, S: Storage<SignalData<T>>> Deref for Signal<T, S> {
-    type Target = dyn Fn() -> S::Ref;
+    type Target =
+        dyn Fn() -> <<S as Storage<SignalData<T>>>::Ref as Mappable<SignalData<T>>>::Mapped<T>;
 
 
     fn deref(&self) -> &Self::Target {
     fn deref(&self) -> &Self::Target {
         // https://github.com/dtolnay/case-studies/tree/master/callable-types
         // https://github.com/dtolnay/case-studies/tree/master/callable-types
@@ -337,21 +386,25 @@ impl<T: 'static, S: Storage<SignalData<T>>> Drop for SignalSubscriberDrop<T, S>
 }
 }
 
 
 /// A mutable reference to a signal's value.
 /// A mutable reference to a signal's value.
-pub struct Write<T: 'static, B: DerefMut<Target = T>, S: Storage<SignalData<I>>, I: 'static = T> {
+///
+/// T is the current type of the write
+/// B is the dynamicly checked type of the write (RefMut)
+/// S is the storage type of the signal
+/// I is the type of the original signal
+pub struct Write<T: 'static, B: MappableMut<T>, S: Storage<SignalData<I>>, I: 'static = T> {
     write: B,
     write: B,
     signal: SignalSubscriberDrop<I, S>,
     signal: SignalSubscriberDrop<I, S>,
+    phantom: std::marker::PhantomData<T>,
 }
 }
 
 
-impl<T: 'static, B: DerefMut<Target = T>, S: Storage<SignalData<I>>, I: 'static> Write<T, B, S, I> {
+impl<T: 'static, B: MappableMut<T>, S: Storage<SignalData<I>>, I: 'static> Write<T, B, S, I> {
     /// Map the mutable reference to the signal's value to a new type.
     /// Map the mutable reference to the signal's value to a new type.
-    pub fn map<O>(myself: Self, f: impl FnOnce(&mut T) -> &mut O) -> Write<O, S::Mapped, S, I>
-    where
-        S: MappableMut<T, O>,
-    {
-        let Self { write, signal } = myself;
+    pub fn map<O>(myself: Self, f: impl FnOnce(&mut T) -> &mut O) -> Write<O, B::Mapped<O>, S, I> {
+        let Self { write, signal, .. } = myself;
         Write {
         Write {
-            write: S::map(write, f),
+            write: B::map(write, f),
             signal,
             signal,
+            phantom: std::marker::PhantomData,
         }
         }
     }
     }
 
 
@@ -359,17 +412,18 @@ impl<T: 'static, B: DerefMut<Target = T>, S: Storage<SignalData<I>>, I: 'static>
     pub fn filter_map<O>(
     pub fn filter_map<O>(
         myself: Self,
         myself: Self,
         f: impl FnOnce(&mut T) -> Option<&mut O>,
         f: impl FnOnce(&mut T) -> Option<&mut O>,
-    ) -> Option<Write<O, S::Mapped, S, I>>
-    where
-        S: MappableMut<T, O>,
-    {
-        let Self { write, signal } = myself;
-        let write = MappedRwLockWriteGuard::try_map(write, f).ok();
-        write.map(|write| Write { write, signal })
+    ) -> Option<Write<O, B::Mapped<O>, S, I>> {
+        let Self { write, signal, .. } = myself;
+        let write = B::try_map(write, f);
+        write.map(|write| Write {
+            write,
+            signal,
+            phantom: PhantomData,
+        })
     }
     }
 }
 }
 
 
-impl<T: 'static, B: DerefMut<Target = T>, S: Storage<SignalData<I>>, I: 'static> Deref
+impl<T: 'static, B: MappableMut<T>, S: Storage<SignalData<I>>, I: 'static> Deref
     for Write<T, B, S, I>
     for Write<T, B, S, I>
 {
 {
     type Target = T;
     type Target = T;
@@ -379,7 +433,7 @@ impl<T: 'static, B: DerefMut<Target = T>, S: Storage<SignalData<I>>, I: 'static>
     }
     }
 }
 }
 
 
-impl<T, B: DerefMut<Target = T>, S: Storage<SignalData<I>>, I> DerefMut for Write<T, B, S, I> {
+impl<T, B: MappableMut<T>, S: Storage<SignalData<I>>, I> DerefMut for Write<T, B, S, I> {
     fn deref_mut(&mut self) -> &mut Self::Target {
     fn deref_mut(&mut self) -> &mut Self::Target {
         &mut self.write
         &mut self.write
     }
     }
@@ -402,7 +456,9 @@ impl<T: 'static, S: Storage<SignalData<T>>> ReadOnlySignal<T, S> {
     }
     }
 
 
     /// Get the current value of the signal. This will subscribe the current scope to the signal.
     /// Get the current value of the signal. This will subscribe the current scope to the signal.
-    pub fn read(&self) -> MappedRwLockReadGuard<'static, T> {
+    pub fn read(
+        &self,
+    ) -> <<S as Storage<SignalData<T>>>::Ref as Mappable<SignalData<T>>>::Mapped<T> {
         self.inner.read()
         self.inner.read()
     }
     }
 
 
@@ -426,7 +482,8 @@ impl<T: 'static, S: Storage<SignalData<T>>> PartialEq for ReadOnlySignal<T, S> {
 }
 }
 
 
 impl<T, S: Storage<SignalData<T>>> Deref for ReadOnlySignal<T, S> {
 impl<T, S: Storage<SignalData<T>>> Deref for ReadOnlySignal<T, S> {
-    type Target = dyn Fn() -> S::Ref;
+    type Target =
+        dyn Fn() -> <<S as Storage<SignalData<T>>>::Ref as Mappable<SignalData<T>>>::Mapped<T>;
 
 
     fn deref(&self) -> &Self::Target {
     fn deref(&self) -> &Self::Target {
         // https://github.com/dtolnay/case-studies/tree/master/callable-types
         // https://github.com/dtolnay/case-studies/tree/master/callable-types