wip: more refactor for async

This commit is contained in:
Jonathan Kelley committed 2021-07-09 12:47:41 -04:00
1 parent 8cfc437bfe
commit 975fa566f9
18 files changed
+110 -122

No files matched your search

+8 -16
View File
@@ -147,18 +147,18 @@ impl<'src, P> Context<'src, P> {
cleanup: impl FnOnce(InternalHookState),
) -> Output {
// If the idx is the same as the hook length, then we need to add the current hook
if self.scope.hooks.is_finished() {
if self.scope.hooks.at_end() {
let new_state = initializer();
self.scope.hooks.push(Box::new(new_state));
self.scope.hooks.push(new_state);
}
let state = self.scope.hooks.next::<InternalHookState>().expect(
r###"
Unable to retrive the hook that was initialized in this index.
Consult the `rules of hooks` to understand how to use hooks properly.
You likely used the hook in a conditional. Hooks rely on consistent ordering between renders.
Any function prefixed with "use" should not be called conditionally.
Unable to retrive the hook that was initialized in this index.
Consult the `rules of hooks` to understand how to use hooks properly.
You likely used the hook in a conditional. Hooks rely on consistent ordering between renders.
Any function prefixed with "use" should not be called conditionally.
"###,
);
@@ -299,16 +299,8 @@ Any function prefixed with "use" should not be called conditionally.
///
///
///
pub fn submit_task(
&self,
mut task: &'src mut DTask<'src>,
// mut task: &'src mut Pin<Box<dyn Future<Output = ()> + 'static>>,
) -> TaskHandle {
pub fn submit_task(&self, mut task: &'src mut DTask<'src>) -> TaskHandle {
self.tasks.push(task);
// let mut g = self.task.borrow_mut();
// *g = Some(task);
// the pointer to the task is stable - we guarantee stability of all &'src references
// let task_ptr = task as *mut _;
TaskHandle { _p: PhantomData {} }
}
+4 -1
View File
@@ -22,7 +22,7 @@
//! More info on how to improve this diffing algorithm:
//! - https://hacks.mozilla.org/2019/03/fast-bump-allocated-virtual-doms-with-rust-and-wasm/
use crate::{arena::SharedArena, innerlude::*};
use crate::{arena::SharedArena, innerlude::*, tasks::TaskQueue};
use fxhash::{FxHashMap, FxHashSet};
use std::{
@@ -94,6 +94,7 @@ pub trait RealDom<'a> {
pub struct DiffMachine<'real, 'bump, Dom: RealDom<'bump>> {
pub dom: &'real mut Dom,
pub components: &'bump SharedArena,
pub task_queue: &'bump TaskQueue,
pub cur_idx: ScopeIdx,
pub diffed: FxHashSet<ScopeIdx>,
pub event_queue: EventQueue,
@@ -106,12 +107,14 @@ impl<'real, 'bump, Dom: RealDom<'bump>> DiffMachine<'real, 'bump, Dom> {
components: &'bump SharedArena,
cur_idx: ScopeIdx,
event_queue: EventQueue,
task_queue: &'bump TaskQueue,
) -> Self {
Self {
components,
dom,
cur_idx,
event_queue,
task_queue,
diffed: FxHashSet::default(),
seen_nodes: FxHashSet::default(),
}
+2 -2
View File
@@ -59,7 +59,7 @@ impl HookList {
}
#[inline]
pub(crate) fn is_finished(&self) -> bool {
self.idx.get() == self.vals.len()
pub(crate) fn at_end(&self) -> bool {
self.cur_idx() >= self.len()
}
}
+1
View File
@@ -61,6 +61,7 @@ pub mod prelude {
use crate::nodes;
pub use crate::styles::{AsAttr, StyleBuilder};
pub use crate::util::RealDomNode;
pub use nodes::*;
pub use crate::nodebuilder::LazyNodes;
+10 -3
View File
@@ -9,6 +9,7 @@ use crate::{
innerlude::{Context, Properties, RealDom, RealDomNode, Scope, ScopeIdx, FC},
nodebuilder::{text3, NodeFactory},
};
use appendlist::AppendList;
use bumpalo::Bump;
use std::{
cell::{Cell, RefCell},
@@ -417,19 +418,25 @@ impl<'a> VComponent<'a> {
type Captured<'a> = Rc<dyn for<'r> Fn(&'r Scope) -> VNode<'r> + 'a>;
fn create_closure<'a, P: 'a>(
component: FC<P>,
user_component: FC<P>,
raw_props: *const (),
) -> Rc<dyn for<'r> Fn(&'r Scope) -> VNode<'r>> {
let g: Captured = Rc::new(move |scp: &Scope| -> VNode {
// cast back into the right lifetime
let safe_props: &'_ P = unsafe { &*(raw_props as *const P) };
let tasks = AppendList::new();
let cx: Context<P> = Context {
props: safe_props,
scope: scp,
tasks: todo!(),
tasks: &tasks,
};
let g = component(cx);
let g = user_component(cx);
// collect the submitted tasks
println!("tasks submittted: {:#?}", tasks.len());
// log::debug!("tasks submittted: {:#?}", tasks.len());
let g2 = unsafe { std::mem::transmute(g) };
g2
});
+11 -9
View File
@@ -39,15 +39,15 @@ impl TaskQueue {
Self { slots, submitter }
}
fn push_task(&mut self, task: DTask) -> TaskHandle {
pub fn submit_task(&mut self, task: DTask) -> TaskHandle {
let key = self.slots.write().unwrap().insert(task);
TaskHandle {}
TaskHandle { key }
}
fn is_empty(&self) -> bool {
pub fn is_empty(&self) -> bool {
self.slots.read().unwrap().is_empty()
}
fn len(&self) -> usize {
pub fn len(&self) -> usize {
self.slots.read().unwrap().len()
}
}
@@ -99,7 +99,9 @@ impl Stream for TaskQueue {
}
}
struct TaskHandle {}
pub struct TaskHandle {
key: DefaultKey,
}
pub struct DTask {
fut: *mut Pin<Box<dyn Future<Output = ()>>>,
@@ -114,7 +116,7 @@ impl DTask {
dead: Cell::new(false),
}
}
fn debug_new(fut: &mut Pin<Box<dyn Future<Output = ()>>>) -> Self {
pub fn debug_new(fut: &mut Pin<Box<dyn Future<Output = ()>>>) -> Self {
let originator = ScopeIdx::default();
Self {
fut,
@@ -154,9 +156,9 @@ mod tests {
}) as RawTask);
let mut queue = TaskQueue::new();
queue.push_task(DTask::debug_new(f1));
queue.push_task(DTask::debug_new(f2));
queue.push_task(DTask::debug_new(f3));
queue.submit_task(DTask::debug_new(f1));
queue.submit_task(DTask::debug_new(f2));
queue.submit_task(DTask::debug_new(f3));
while !queue.is_empty() {
let next = queue.next().await;
+26 -6
View File
@@ -21,6 +21,7 @@
use crate::tasks::TaskQueue;
use crate::{arena::SharedArena, innerlude::*};
use appendlist::AppendList;
use slotmap::DefaultKey;
use slotmap::SlotMap;
use std::{any::TypeId, fmt::Debug, rc::Rc};
@@ -130,16 +131,29 @@ impl VirtualDom {
// Normally, a component would be passed as a child in the RSX macro which automatically produces OpaqueComponents
// Here, we need to make it manually, using an RC to force the Weak reference to stick around for the main scope.
let _root_caller: Rc<WrappedCaller> = Rc::new(move |scope| {
let _root_caller: Rc<WrappedCaller> = Rc::new(move |scope: &Scope| {
// let _root_caller: Rc<OpaqueComponent<'static>> = Rc::new(move |scope| {
// the lifetime of this closure is just as long as the lifetime on the scope reference
// this closure moves root props (which is static) into this closure
let props = unsafe { &*(&root_props as *const _) };
root(Context {
let tasks = AppendList::new();
let t2 = &tasks;
let cx = Context {
props,
scope,
tasks: todo!(),
})
tasks: t2,
};
let nodes = root(cx);
log::debug!("There were {:?} tasks submitted", tasks.len());
// cast a weird lifetime to shake the appendlist thing
// TODO: move all of this into the same logic that governs other components
// we want to wrap everything in a dioxus root component
unsafe { std::mem::transmute(nodes) }
// std::mem::drop(tasks);
//
// nodes
});
// Create a weak reference to the OpaqueComponent for the root scope to use as its render function
@@ -185,6 +199,7 @@ impl VirtualDom {
&self.components,
self.base_scope,
self.event_queue.clone(),
&self.tasks,
);
// Schedule an update and then immediately call it on the root component
@@ -251,8 +266,13 @@ impl VirtualDom {
self.components.try_get_mut(id)?.call_listener(trigger)?;
let mut diff_machine =
DiffMachine::new(realdom, &self.components, id, self.event_queue.clone());
let mut diff_machine = DiffMachine::new(
realdom,
&self.components,
id,
self.event_queue.clone(),
&self.tasks,
);
self.progress_completely(&mut diff_machine)?;