unqueue tasks when a scope is dropped
This commit is contained in:
1 parent
701093ede5
commit
d28221bdc2
4 files changed
+21
-18
No files matched your search
@@ -68,18 +68,13 @@ impl VirtualDom {
|
|||||||
//
|
//
|
||||||
// Note: This will not remove any ids from the arena
|
// Note: This will not remove any ids from the arena
|
||||||
pub(crate) fn drop_scope(&mut self, id: ScopeId) {
|
pub(crate) fn drop_scope(&mut self, id: ScopeId) {
|
||||||
let (height, spawned_tasks) = {
|
let height = {
|
||||||
let scope = self.scopes.remove(id.0);
|
let scope = self.scopes.remove(id.0);
|
||||||
let context = scope.context();
|
let context = scope.context();
|
||||||
let spawned_tasks = context.spawned_tasks.borrow();
|
context.height
|
||||||
let spawned_tasks: Vec<_> = spawned_tasks.iter().copied().collect();
|
|
||||||
(context.height, spawned_tasks)
|
|
||||||
};
|
};
|
||||||
|
|
||||||
self.dirty_scopes.remove(&DirtyScope { height, id });
|
self.dirty_scopes.remove(&DirtyScope { height, id });
|
||||||
for task in spawned_tasks {
|
|
||||||
self.runtime.remove_task(task);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ use crate::{
|
|||||||
};
|
};
|
||||||
use std::{
|
use std::{
|
||||||
cell::{Cell, Ref, RefCell},
|
cell::{Cell, Ref, RefCell},
|
||||||
|
collections::VecDeque,
|
||||||
rc::Rc,
|
rc::Rc,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -28,6 +29,9 @@ pub struct Runtime {
|
|||||||
/// Tasks created with cx.spawn
|
/// Tasks created with cx.spawn
|
||||||
pub(crate) tasks: RefCell<slab::Slab<LocalTask>>,
|
pub(crate) tasks: RefCell<slab::Slab<LocalTask>>,
|
||||||
|
|
||||||
|
/// Queued tasks that are waiting to be polled
|
||||||
|
pub(crate) queued_tasks: Rc<RefCell<VecDeque<Task>>>,
|
||||||
|
|
||||||
pub(crate) sender: futures_channel::mpsc::UnboundedSender<SchedulerMsg>,
|
pub(crate) sender: futures_channel::mpsc::UnboundedSender<SchedulerMsg>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -40,6 +44,7 @@ impl Runtime {
|
|||||||
scope_stack: Default::default(),
|
scope_stack: Default::default(),
|
||||||
current_task: Default::default(),
|
current_task: Default::default(),
|
||||||
tasks: Default::default(),
|
tasks: Default::default(),
|
||||||
|
queued_tasks: Rc::new(RefCell::new(VecDeque::new())),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -112,11 +112,21 @@ impl Runtime {
|
|||||||
self.current_task.set(None);
|
self.current_task.set(None);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Take a queued task from the scheduler
|
||||||
|
pub(crate) fn take_queued_task(&self) -> Option<Task> {
|
||||||
|
self.queued_tasks.borrow_mut().pop_front()
|
||||||
|
}
|
||||||
|
|
||||||
/// Drop the future with the given TaskId
|
/// Drop the future with the given TaskId
|
||||||
///
|
///
|
||||||
/// This does not abort the task, so you'll want to wrap it in an abort handle if that's important to you
|
/// This does not abort the task, so you'll want to wrap it in an abort handle if that's important to you
|
||||||
pub(crate) fn remove_task(&self, id: Task) -> Option<LocalTask> {
|
pub(crate) fn remove_task(&self, id: Task) -> Option<LocalTask> {
|
||||||
self.tasks.borrow_mut().try_remove(id.0)
|
let task = self.tasks.borrow_mut().try_remove(id.0);
|
||||||
|
|
||||||
|
// Remove the task from the queued tasks so we don't poll a different task with the same id
|
||||||
|
self.queued_tasks.borrow_mut().retain(|t| *t != id);
|
||||||
|
|
||||||
|
task
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the currently running task
|
/// Get the currently running task
|
||||||
|
|||||||
@@ -19,12 +19,7 @@ use crate::{
|
|||||||
use futures_util::{pin_mut, StreamExt};
|
use futures_util::{pin_mut, StreamExt};
|
||||||
use rustc_hash::{FxHashMap, FxHashSet};
|
use rustc_hash::{FxHashMap, FxHashSet};
|
||||||
use slab::Slab;
|
use slab::Slab;
|
||||||
use std::{
|
use std::{any::Any, collections::BTreeSet, future::Future, rc::Rc};
|
||||||
any::Any,
|
|
||||||
collections::{BTreeSet, VecDeque},
|
|
||||||
future::Future,
|
|
||||||
rc::Rc,
|
|
||||||
};
|
|
||||||
|
|
||||||
/// A virtual node system that progresses user events and diffs UI trees.
|
/// A virtual node system that progresses user events and diffs UI trees.
|
||||||
///
|
///
|
||||||
@@ -189,7 +184,6 @@ pub struct VirtualDom {
|
|||||||
pub(crate) scopes: Slab<ScopeState>,
|
pub(crate) scopes: Slab<ScopeState>,
|
||||||
|
|
||||||
pub(crate) dirty_scopes: BTreeSet<DirtyScope>,
|
pub(crate) dirty_scopes: BTreeSet<DirtyScope>,
|
||||||
pub(crate) dirty_tasks: VecDeque<Task>,
|
|
||||||
|
|
||||||
// Maps a template path to a map of byte indexes to templates
|
// Maps a template path to a map of byte indexes to templates
|
||||||
pub(crate) templates: FxHashMap<TemplateId, FxHashMap<usize, Template>>,
|
pub(crate) templates: FxHashMap<TemplateId, FxHashMap<usize, Template>>,
|
||||||
@@ -284,7 +278,6 @@ impl VirtualDom {
|
|||||||
runtime: Runtime::new(tx),
|
runtime: Runtime::new(tx),
|
||||||
scopes: Default::default(),
|
scopes: Default::default(),
|
||||||
dirty_scopes: Default::default(),
|
dirty_scopes: Default::default(),
|
||||||
dirty_tasks: Default::default(),
|
|
||||||
templates: Default::default(),
|
templates: Default::default(),
|
||||||
queued_templates: Default::default(),
|
queued_templates: Default::default(),
|
||||||
elements: Default::default(),
|
elements: Default::default(),
|
||||||
@@ -420,7 +413,7 @@ impl VirtualDom {
|
|||||||
|
|
||||||
if !has_dirty_scopes {
|
if !has_dirty_scopes {
|
||||||
// If we have no dirty scopes, then we should poll any tasks that have been notified
|
// If we have no dirty scopes, then we should poll any tasks that have been notified
|
||||||
while let Some(task) = self.dirty_tasks.pop_front() {
|
while let Some(task) = self.runtime.take_queued_task() {
|
||||||
self.handle_task_wakeup(task);
|
self.handle_task_wakeup(task);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -626,7 +619,7 @@ impl VirtualDom {
|
|||||||
|
|
||||||
/// Queue a task to be polled after all dirty scopes have been rendered
|
/// Queue a task to be polled after all dirty scopes have been rendered
|
||||||
fn queue_task_wakeup(&mut self, id: Task) {
|
fn queue_task_wakeup(&mut self, id: Task) {
|
||||||
self.dirty_tasks.push_back(id);
|
self.runtime.queued_tasks.borrow_mut().push_back(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Handle notifications by tasks inside the scheduler
|
/// Handle notifications by tasks inside the scheduler
|
||||||
|
|||||||
Reference in new issue
Block a user