浏览代码

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

Use linear scans when searching for contexts
Jon Kelley 2 年之前
父节点
当前提交
7eeb72b929
共有 1 个文件被更改,包括 25 次插入10 次删除
  1. 25 10
      packages/core/src/scopes.rs

+ 25 - 10
packages/core/src/scopes.rs

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