feat: wire tasks up

This commit is contained in:
Jonathan Kelley committed 2021-11-12 01:36:33 -05:00
1 parent 9d8c5ca5ab
commit 55e6dd9701
3 files changed
+32 -17

No files matched your search

+26 -13
View File
@@ -7,6 +7,7 @@ use futures_channel::mpsc::{UnboundedReceiver, UnboundedSender};
use futures_util::{Future, StreamExt};
use fxhash::FxHashSet;
use indexmap::IndexSet;
use smallvec::SmallVec;
use std::pin::Pin;
use std::rc::Rc;
use std::sync::Arc;
@@ -116,8 +117,6 @@ pub struct VirtualDom {
sender: UnboundedSender<SchedulerMsg>,
pending_futures: FxHashSet<ScopeId>,
pending_messages: VecDeque<SchedulerMsg>,
dirty_scopes: IndexSet<ScopeId>,
@@ -210,7 +209,6 @@ impl VirtualDom {
receiver,
_root_props: caller,
pending_messages,
pending_futures: Default::default(),
dirty_scopes,
sender,
}
@@ -266,45 +264,61 @@ impl VirtualDom {
// todo: poll the events once even if there is work to do to prevent starvation
// if there's no futures in the virtualdom, just wait for a scheduler message and put it into the queue to be processed
if self.pending_futures.is_empty() {
if self.scopes.pending_futures.is_empty() {
self.pending_messages
.push_front(self.receiver.next().await.unwrap());
} else {
struct PollTasks<'a> {
pending_futures: &'a FxHashSet<ScopeId>,
scopes: &'a ScopeArena,
scopes: &'a mut ScopeArena,
}
impl<'a> Future for PollTasks<'a> {
type Output = ();
fn poll(
self: Pin<&mut Self>,
mut self: Pin<&mut Self>,
cx: &mut std::task::Context<'_>,
) -> Poll<Self::Output> {
let mut all_pending = true;
let mut unfinished_tasks: SmallVec<[_; 10]> = smallvec::smallvec![];
let mut scopes_to_clear: SmallVec<[_; 10]> = smallvec::smallvec![];
// Poll every scope manually
for fut in self.pending_futures.iter() {
for fut in self.scopes.pending_futures.iter() {
let scope = self
.scopes
.get_scope(fut)
.expect("Scope should never be moved");
let mut items = scope.items.borrow_mut();
for task in items.tasks.iter_mut() {
let task = task.as_mut();
while let Some(mut task) = items.tasks.pop() {
// todo: does this make sense?
// I don't usually write futures by hand
// I think the futures neeed to be pinned using bumpbox or something
// right now, they're bump allocated so this shouldn't matter anyway - they're not going to move
let unpinned = unsafe { Pin::new_unchecked(task) };
let task_mut = task.as_mut();
let unpinned = unsafe { Pin::new_unchecked(task_mut) };
if unpinned.poll(cx).is_ready() {
all_pending = false
} else {
unfinished_tasks.push(task);
}
}
if unfinished_tasks.is_empty() {
scopes_to_clear.push(*fut);
}
for task in unfinished_tasks.drain(..) {
items.tasks.push(task);
}
}
for scope in scopes_to_clear {
self.scopes.pending_futures.remove(&scope);
}
// Resolve the future if any singular task is ready
@@ -320,8 +334,7 @@ impl VirtualDom {
let scheduler_fut = self.receiver.next();
let tasks_fut = PollTasks {
pending_futures: &self.pending_futures,
scopes: &self.scopes,
scopes: &mut self.scopes,
};
match select(tasks_fut, scheduler_fut).await {