wip: got the structure figured out!

This commit is contained in:
Jonathan Kelley committed 2021-08-10 01:21:13 -04:00
1 parent 85e2dc259a
commit 97745c6a7f
2 files changed
+235 -80

No files matched your search

+139 -3
View File
@@ -5,6 +5,8 @@ use std::cell::{Ref, RefCell, RefMut};
use std::collections::{BTreeMap, BTreeSet, BinaryHeap, HashMap, HashSet, VecDeque};
use std::pin::Pin;
use futures_util::Future;
use crate::innerlude::*;
/// The "Mutations" object holds the changes that need to be made to the DOM.
@@ -45,16 +47,33 @@ impl<'a> NodeRefMutation<'a> {
pub struct Scheduler {
current_priority: EventPriority,
pending_events: VecDeque<EventTrigger>,
pending_immediates: VecDeque<EventTrigger>,
pending_tasks: VecDeque<EventTrigger>,
garbage_scopes: HashSet<ScopeId>,
shared: SharedResources,
dirty_scopes: [HashSet<DirtyScope>; 3],
fibers: Vec<Fiber<'static>>,
}
impl Scheduler {
pub fn new() -> Self {
pub fn new(shared: SharedResources) -> Self {
Self {
shared,
// a storage for our receiver to dump into
pending_events: VecDeque::new(),
pending_immediates: VecDeque::new(),
pending_tasks: VecDeque::new(),
fibers: Vec::new(),
garbage_scopes: HashSet::new(),
current_priority: EventPriority::Low,
// low, medium, high
@@ -62,6 +81,64 @@ impl Scheduler {
}
}
// channels don't have these methods, so we just implement our own wrapper
pub fn next_event(&mut self) -> Option<EventTrigger> {
// pop the last event off the internal queue
self.pending_events.pop_back().or_else(|| {
self.shared
.ui_event_receiver
.borrow_mut()
.try_next()
.ok()
.and_then(|f| f)
})
}
// waits for a trigger, canceling early if the deadline is reached
// returns true if the deadline was reached
pub async fn wait_for_any_trigger(&mut self, deadline: &mut impl Future<Output = ()>) -> bool {
todo!()
// match raw_trigger {
// Ok(Some(trigger)) => trigger,
// _ => {
// // nothing to do - let's clean up any garbage we might have
// self.scheduler.clean_up_garbage();
// // Continuously poll the future pool and the event receiver for work
// let mut tasks = self.shared.async_tasks.borrow_mut();
// let tasks_tasks = tasks.next();
// // if the new event generates work more important than our current fiber, we should consider switching
// // only switch if it impacts different scopes.
// let mut ui_receiver = self.shared.ui_event_receiver.borrow_mut();
// let ui_reciv_task = ui_receiver.next();
// // right now, this polling method will only catch batched set_states that don't get awaited.
// // However, in the future, we might be interested in batching set_states across await points
// let immediate_tasks = ();
// futures_util::pin_mut!(tasks_tasks);
// futures_util::pin_mut!(ui_reciv_task);
// // Poll the event receiver and the future pool for work
// // Abort early if our deadline has ran out
// let mut deadline = (&mut deadline_future).fuse();
// let trig = futures_util::select! {
// trigger = tasks_tasks => trigger,
// trigger = ui_reciv_task => trigger,
// // abort if we're out of time
// _ = deadline => { return Ok(Mutations::new()); }
// // _ = deadline => { return Ok(diff_machine.mutations); }
// };
// trig.unwrap()
// }
// };
//
}
pub fn add_dirty_scope(&mut self, scope: ScopeId, priority: EventPriority) {
//
@@ -75,9 +152,68 @@ impl Scheduler {
// .or_insert_with(|| new_priority);
}
pub fn has_work() {}
pub fn has_work(&self) -> bool {
true
}
pub fn progress_work(&mut self, machine: &mut DiffMachine) {}
// returns true if the deadline is reached
// returns false if the deadline is not reached
pub fn progress_work(
&mut self,
machine: &mut DiffMachine,
is_deadline_reached: &mut impl FnMut() -> bool,
) -> bool {
todo!()
}
pub fn clean_up_garbage(&mut self) {
let mut scopes_to_kill = Vec::new();
let mut garbage_list = Vec::new();
for scope in self.garbage_scopes.drain() {
let scope = self.shared.get_scope_mut(scope).unwrap();
for node in scope.consume_garbage() {
garbage_list.push(node);
}
while let Some(node) = garbage_list.pop() {
match &node.kind {
VNodeKind::Text(_) => {
self.shared.collect_garbage(node.direct_id());
}
VNodeKind::Anchor(_) => {
self.shared.collect_garbage(node.direct_id());
}
VNodeKind::Suspended(_) => {
self.shared.collect_garbage(node.direct_id());
}
VNodeKind::Element(el) => {
self.shared.collect_garbage(node.direct_id());
for child in el.children {
garbage_list.push(child);
}
}
VNodeKind::Fragment(frag) => {
for child in frag.children {
garbage_list.push(child);
}
}
VNodeKind::Component(comp) => {
// TODO: run the hook destructors and then even delete the scope
let scope_id = comp.ass_scope.get().unwrap();
let scope = self.shared.get_scope(scope_id).unwrap();
let root = scope.root();
garbage_list.push(root);
scopes_to_kill.push(scope_id);
}
}
}
}
}
}
#[derive(PartialEq, Eq, Copy, Clone, Debug)]