wip: refactor
This commit is contained in:
1 parent
9ad5e49654
commit
8b0eb87c72
13 files changed
+96
-128
No files matched your search
+11
-23
@@ -106,7 +106,6 @@ use DomEdit::*;
|
||||
/// Funnily enough, this stack machine's entire job is to create instructions for another stack machine to execute. It's
|
||||
/// stack machines all the way down!
|
||||
pub struct DiffMachine<'bump> {
|
||||
pub channel: EventChannel,
|
||||
pub vdom: &'bump ResourcePool,
|
||||
pub mutations: Mutations<'bump>,
|
||||
pub stack: DiffStack<'bump>,
|
||||
@@ -117,7 +116,6 @@ pub struct DiffMachine<'bump> {
|
||||
/// in regular diff machine, the &'bump reference is a stack borrow, but the
|
||||
/// bump lifetimes are heap borrows.
|
||||
pub struct SavedDiffWork<'bump> {
|
||||
pub channel: EventChannel,
|
||||
pub mutations: Mutations<'bump>,
|
||||
pub stack: DiffStack<'bump>,
|
||||
pub seen_scopes: FxHashSet<ScopeId>,
|
||||
@@ -131,7 +129,6 @@ impl<'a> SavedDiffWork<'a> {
|
||||
let extended: SavedDiffWork<'b> = std::mem::transmute(self);
|
||||
DiffMachine {
|
||||
vdom,
|
||||
channel: extended.channel,
|
||||
mutations: extended.mutations,
|
||||
stack: extended.stack,
|
||||
seen_scopes: extended.seen_scopes,
|
||||
@@ -140,13 +137,8 @@ impl<'a> SavedDiffWork<'a> {
|
||||
}
|
||||
|
||||
impl<'bump> DiffMachine<'bump> {
|
||||
pub(crate) fn new(
|
||||
edits: Mutations<'bump>,
|
||||
shared: &'bump mut ResourcePool,
|
||||
channel: EventChannel,
|
||||
) -> Self {
|
||||
pub(crate) fn new(edits: Mutations<'bump>, shared: &'bump mut ResourcePool) -> Self {
|
||||
Self {
|
||||
channel,
|
||||
stack: DiffStack::new(),
|
||||
mutations: edits,
|
||||
vdom: shared,
|
||||
@@ -156,7 +148,6 @@ impl<'bump> DiffMachine<'bump> {
|
||||
|
||||
pub fn save(self) -> SavedDiffWork<'bump> {
|
||||
SavedDiffWork {
|
||||
channel: self.channel,
|
||||
mutations: self.mutations,
|
||||
stack: self.stack,
|
||||
seen_scopes: self.seen_scopes,
|
||||
@@ -208,12 +199,10 @@ impl<'bump> DiffMachine<'bump> {
|
||||
}
|
||||
|
||||
DiffInstruction::PrepareMoveNode { node } => {
|
||||
log::debug!("Preparing to move node: {:?}", node);
|
||||
todo!();
|
||||
// for el in RealChildIterator::new(node, self.vdom) {
|
||||
// self.mutations.push_root(el.direct_id());
|
||||
// self.stack.add_child_count(1);
|
||||
// }
|
||||
for el in RealChildIterator::new(node, self.vdom) {
|
||||
self.mutations.push_root(el.direct_id());
|
||||
self.stack.add_child_count(1);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -237,12 +226,11 @@ impl<'bump> DiffMachine<'bump> {
|
||||
}
|
||||
|
||||
MountType::Replace { old } => {
|
||||
todo!()
|
||||
// let mut iter = RealChildIterator::new(old, self.vdom);
|
||||
// let first = iter.next().unwrap();
|
||||
// self.mutations
|
||||
// .replace_with(first.direct_id(), nodes_created as u32);
|
||||
// self.remove_nodes(iter);
|
||||
let mut iter = RealChildIterator::new(old, self.vdom);
|
||||
let first = iter.next().unwrap();
|
||||
self.mutations
|
||||
.replace_with(first.direct_id(), nodes_created as u32);
|
||||
self.remove_nodes(iter);
|
||||
}
|
||||
|
||||
MountType::ReplaceByElementId { el: old } => {
|
||||
@@ -343,7 +331,7 @@ impl<'bump> DiffMachine<'bump> {
|
||||
|
||||
let parent_idx = self.stack.current_scope().unwrap();
|
||||
|
||||
let shared = self.channel.clone();
|
||||
let shared = self.vdom.channel.clone();
|
||||
// Insert a new scope into our component list
|
||||
let parent_scope = self.vdom.get_scope(parent_idx).unwrap();
|
||||
let new_idx = self.vdom.insert_scope_with_key(|new_idx| {
|
||||
|
||||
@@ -15,11 +15,6 @@ pub struct EventTrigger {
|
||||
|
||||
/// The type of event
|
||||
pub event: SyntheticEvent,
|
||||
|
||||
/// Is consistency important for this event?
|
||||
/// UI events are the only events where consistency is important.
|
||||
/// All else may be batched.
|
||||
pub discrete: bool,
|
||||
}
|
||||
|
||||
pub enum SyntheticEvent {
|
||||
|
||||
@@ -133,8 +133,6 @@ pub struct Scheduler {
|
||||
|
||||
pub heuristics: HeuristicsEngine,
|
||||
|
||||
pub channel: EventChannel,
|
||||
|
||||
pub receiver: UnboundedReceiver<SchedulerMsg>,
|
||||
|
||||
// Garbage stored
|
||||
@@ -166,11 +164,6 @@ impl Scheduler {
|
||||
let components = Rc::new(UnsafeCell::new(Slab::with_capacity(100)));
|
||||
let raw_elements = Rc::new(UnsafeCell::new(Slab::with_capacity(2000)));
|
||||
|
||||
let pool = ResourcePool {
|
||||
components: components.clone(),
|
||||
raw_elements,
|
||||
};
|
||||
|
||||
let heuristics = HeuristicsEngine::new();
|
||||
|
||||
let (sender, receiver) = futures_channel::mpsc::unbounded::<SchedulerMsg>();
|
||||
@@ -214,9 +207,14 @@ impl Scheduler {
|
||||
},
|
||||
};
|
||||
|
||||
let pool = ResourcePool {
|
||||
components: components.clone(),
|
||||
raw_elements,
|
||||
channel,
|
||||
};
|
||||
|
||||
Self {
|
||||
pool,
|
||||
channel,
|
||||
receiver,
|
||||
|
||||
async_tasks: FuturesUnordered::new(),
|
||||
@@ -253,7 +251,7 @@ impl Scheduler {
|
||||
}
|
||||
|
||||
// Converts UI events into dirty scopes with various priorities
|
||||
pub fn consume_pending_events(&mut self) -> Result<()> {
|
||||
pub fn consume_pending_events(&mut self) {
|
||||
// while let Some(trigger) = self.ui_events.pop_back() {
|
||||
// match &trigger.event {
|
||||
// SyntheticEvent::ClipboardEvent(_)
|
||||
@@ -287,8 +285,6 @@ impl Scheduler {
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// nothing to do, no events on channels, no work
|
||||
@@ -363,8 +359,6 @@ impl Scheduler {
|
||||
/// Uses some fairly complex logic to schedule what work should be produced.
|
||||
///
|
||||
/// Returns a list of successful mutations.
|
||||
///
|
||||
///
|
||||
pub async fn work_with_deadline<'a>(
|
||||
&'a mut self,
|
||||
mut deadline: Pin<Box<impl FusedFuture<Output = ()>>>,
|
||||
@@ -392,10 +386,6 @@ impl Scheduler {
|
||||
*/
|
||||
let mut committed_mutations = Vec::<Mutations<'static>>::new();
|
||||
|
||||
// TODO:
|
||||
// the scheduler uses a bunch of different receivers to mimic a "topic" queue system. The futures-channel implementation
|
||||
// doesn't really have a concept of a "topic" queue, so there's a lot of noise in the hand-rolled scheduler. We should
|
||||
// explore abstracting the scheduler into a topic-queue channel system - similar to Kafka or something similar.
|
||||
loop {
|
||||
// Internalize any pending work since the last time we ran
|
||||
self.manually_poll_events();
|
||||
@@ -411,7 +401,7 @@ impl Scheduler {
|
||||
}
|
||||
|
||||
// Create work from the pending event queue
|
||||
self.consume_pending_events().unwrap();
|
||||
self.consume_pending_events();
|
||||
|
||||
// Work through the current subtree, and commit the results when it finishes
|
||||
// When the deadline expires, give back the work
|
||||
@@ -443,8 +433,8 @@ impl Scheduler {
|
||||
pin_mut!(fut);
|
||||
use futures_util::future::{select, Either};
|
||||
match select(fut, &mut deadline).await {
|
||||
Either::Left((work, _other)) => true,
|
||||
Either::Right((deadline, _other)) => false,
|
||||
Either::Left((_, _other)) => true,
|
||||
Either::Right((_, _other)) => false,
|
||||
}
|
||||
};
|
||||
|
||||
@@ -461,6 +451,7 @@ impl Scheduler {
|
||||
|
||||
committed_mutations.push(new_mutations);
|
||||
}
|
||||
|
||||
self.save_work(saved);
|
||||
|
||||
if !completed {
|
||||
@@ -670,6 +661,8 @@ pub struct ResourcePool {
|
||||
In the future, we could actually store a pointer to the VNode instead of nil to provide O(1) lookup for VNodes...
|
||||
*/
|
||||
pub raw_elements: Rc<UnsafeCell<Slab<()>>>,
|
||||
|
||||
pub channel: EventChannel,
|
||||
}
|
||||
|
||||
impl ResourcePool {
|
||||
@@ -711,8 +704,8 @@ impl ResourcePool {
|
||||
}
|
||||
|
||||
pub fn reserve_node(&self) -> ElementId {
|
||||
todo!("reserving wip until it's fast enough again")
|
||||
// ElementId(self.raw_elements.insert(()))
|
||||
let els = unsafe { &mut *self.raw_elements.get() };
|
||||
ElementId(els.insert(()))
|
||||
}
|
||||
|
||||
/// return the id, freeing the space of the original node
|
||||
|
||||
@@ -164,7 +164,7 @@ impl Scope {
|
||||
"clean up your garabge please"
|
||||
);
|
||||
|
||||
todo!("arch changes");
|
||||
// todo!("arch changes");
|
||||
|
||||
// // make sure we drop all borrowed props manually to guarantee that their drop implementation is called before we
|
||||
// // run the hooks (which hold an &mut Referrence)
|
||||
|
||||
@@ -116,7 +116,7 @@ impl VirtualDom {
|
||||
None,
|
||||
0,
|
||||
ScopeChildren(&[]),
|
||||
scheduler.channel.clone(),
|
||||
scheduler.pool.channel.clone(),
|
||||
)
|
||||
});
|
||||
|
||||
@@ -158,29 +158,31 @@ impl VirtualDom {
|
||||
/// the diff and creating nodes can be expensive, so we provide this method to avoid blocking the main thread. This
|
||||
/// method can be useful when needing to perform some crucial periodic tasks.
|
||||
pub async fn rebuild_async<'s>(&'s mut self) -> Mutations<'s> {
|
||||
todo!()
|
||||
// let mut diff_machine = DiffMachine::new(Mutations::new(), self.base_scope, &self.scheduler);
|
||||
let mut shared = self.scheduler.pool.clone();
|
||||
let mut diff_machine = DiffMachine::new(Mutations::new(), &mut shared);
|
||||
|
||||
// let cur_component = self
|
||||
// .scheduler
|
||||
// .get_scope_mut(self.base_scope)
|
||||
// .expect("The base scope should never be moved");
|
||||
let cur_component = self
|
||||
.scheduler
|
||||
.pool
|
||||
.get_scope_mut(self.base_scope)
|
||||
.expect("The base scope should never be moved");
|
||||
|
||||
// // // We run the component. If it succeeds, then we can diff it and add the changes to the dom.
|
||||
// if cur_component.run_scope().is_ok() {
|
||||
// diff_machine
|
||||
// .stack
|
||||
// .create_node(cur_component.frames.fin_head(), MountType::Append);
|
||||
// diff_machine.work().await;
|
||||
// } else {
|
||||
// // todo: should this be a hard error?
|
||||
// log::warn!(
|
||||
// "Component failed to run succesfully during rebuild.
|
||||
// This does not result in a failed rebuild, but indicates a logic failure within your app."
|
||||
// );
|
||||
// }
|
||||
// // We run the component. If it succeeds, then we can diff it and add the changes to the dom.
|
||||
if cur_component.run_scope().is_ok() {
|
||||
diff_machine
|
||||
.stack
|
||||
.create_node(cur_component.frames.fin_head(), MountType::Append);
|
||||
diff_machine.stack.scope_stack.push(self.base_scope);
|
||||
diff_machine.work().await;
|
||||
} else {
|
||||
// todo: should this be a hard error?
|
||||
log::warn!(
|
||||
"Component failed to run succesfully during rebuild.
|
||||
This does not result in a failed rebuild, but indicates a logic failure within your app."
|
||||
);
|
||||
}
|
||||
|
||||
// diff_machine.mutations
|
||||
unsafe { std::mem::transmute(diff_machine.mutations) }
|
||||
}
|
||||
|
||||
pub fn diff_sync<'s>(&'s mut self) -> Mutations<'s> {
|
||||
@@ -194,7 +196,7 @@ impl VirtualDom {
|
||||
}
|
||||
|
||||
pub async fn diff_async<'s>(&'s mut self) -> Mutations<'s> {
|
||||
let mut diff_machine = DiffMachine::new(Mutations::new(), todo!(), todo!());
|
||||
let mut diff_machine = DiffMachine::new(Mutations::new(), todo!());
|
||||
|
||||
let cur_component = self
|
||||
.scheduler
|
||||
@@ -273,7 +275,7 @@ impl VirtualDom {
|
||||
}
|
||||
|
||||
pub fn get_event_sender(&self) -> futures_channel::mpsc::UnboundedSender<SchedulerMsg> {
|
||||
self.scheduler.channel.sender.clone()
|
||||
self.scheduler.pool.channel.sender.clone()
|
||||
}
|
||||
|
||||
pub fn has_work(&self) -> bool {
|
||||
|
||||
Reference in new issue
Block a user