Merge pull request #1162 from DioxusLabs/jk/use-linear-scans

Use linear scans when searching for contexts
This commit is contained in:
Jon Kelley authored and GitHub committed 2023-07-07 13:51:25 -07:00
commit 7eeb72b929
1 file changed
+25 -10
+25 -10
View File
@@ -11,7 +11,7 @@ use crate::{
}; };
use bumpalo::{boxed::Box as BumpBox, Bump}; use bumpalo::{boxed::Box as BumpBox, Bump};
use bumpslab::{BumpSlab, Slot}; use bumpslab::{BumpSlab, Slot};
use rustc_hash::{FxHashMap, FxHashSet}; use rustc_hash::FxHashSet;
use slab::{Slab, VacantEntry}; use slab::{Slab, VacantEntry};
use std::{ use std::{
any::{Any, TypeId}, any::{Any, TypeId},
@@ -173,7 +173,7 @@ pub struct ScopeState {
pub(crate) hooks: RefCell<Vec<Box<UnsafeCell<dyn Any>>>>, pub(crate) hooks: RefCell<Vec<Box<UnsafeCell<dyn Any>>>>,
pub(crate) hook_idx: Cell<usize>, pub(crate) hook_idx: Cell<usize>,
pub(crate) shared_contexts: RefCell<FxHashMap<TypeId, Box<dyn Any>>>, pub(crate) shared_contexts: RefCell<Vec<(TypeId, Box<dyn Any>)>>,
pub(crate) tasks: Rc<Scheduler>, pub(crate) tasks: Rc<Scheduler>,
pub(crate) spawned_tasks: RefCell<FxHashSet<TaskId>>, pub(crate) spawned_tasks: RefCell<FxHashSet<TaskId>>,
@@ -347,7 +347,9 @@ impl<'src> ScopeState {
pub fn has_context<T: 'static + Clone>(&self) -> Option<T> { pub fn has_context<T: 'static + Clone>(&self) -> Option<T> {
self.shared_contexts self.shared_contexts
.borrow() .borrow()
.get(&TypeId::of::<T>())? .iter()
.find(|(k, _)| *k == TypeId::of::<T>())
.map(|(_, v)| v)?
.downcast_ref::<T>() .downcast_ref::<T>()
.cloned() .cloned()
} }
@@ -364,8 +366,13 @@ impl<'src> ScopeState {
while let Some(parent_ptr) = search_parent { while let Some(parent_ptr) = search_parent {
// safety: all parent pointers are valid thanks to the bump arena // safety: all parent pointers are valid thanks to the bump arena
let parent = unsafe { &*parent_ptr }; let parent = unsafe { &*parent_ptr };
if let Some(shared) = parent.shared_contexts.borrow().get(&TypeId::of::<T>()) { if let Some(shared) = parent
return shared.downcast_ref::<T>().cloned(); .shared_contexts
.borrow()
.iter()
.find(|(k, _)| *k == TypeId::of::<T>())
{
return shared.1.downcast_ref::<T>().cloned();
} }
search_parent = parent.parent; search_parent = parent.parent;
} }
@@ -394,13 +401,21 @@ impl<'src> ScopeState {
/// } /// }
/// ``` /// ```
pub fn provide_context<T: 'static + Clone>(&self, value: T) -> T { pub fn provide_context<T: 'static + Clone>(&self, value: T) -> T {
let value2 = value.clone(); let mut contexts = self.shared_contexts.borrow_mut();
self.shared_contexts // If the context exists, swap it out for the new value
.borrow_mut() for ctx in contexts.iter_mut() {
.insert(TypeId::of::<T>(), Box::new(value)); // Swap the ptr directly
if let Some(ctx) = ctx.1.downcast_mut::<T>() {
std::mem::swap(ctx, &mut value.clone());
return value;
}
}
value2 // Else, just push it
contexts.push((TypeId::of::<T>(), Box::new(value.clone())));
value
} }
/// Pushes the future onto the poll queue to be polled after the component renders. /// Pushes the future onto the poll queue to be polled after the component renders.