feat: suspense!

This commit is contained in:
Jonathan Kelley committed 2022-11-07 22:55:22 -08:00
1 parent e6c53803a6
commit 203935834d
13 files changed
+219 -205

No files matched your search

+24 -41
View File
@@ -1,21 +1,24 @@
use std::{collections::HashSet, rc::Rc};
use std::{
cell::{Cell, RefCell},
collections::HashSet,
pin::Pin,
rc::Rc,
};
use futures_task::{RawWaker, RawWakerVTable, Waker};
use super::{waker::RcWake, SchedulerMsg};
use crate::{innerlude::Mutation, Element, ScopeId};
use futures_task::Waker;
use futures_util::Future;
use crate::{innerlude::Mutation, Element, Scope, ScopeId};
use super::SchedulerMsg;
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
pub struct SuspenseId(pub usize);
pub type SuspenseContext = Rc<SuspenseBoundary>;
pub type SuspenseContext = Rc<RefCell<SuspenseBoundary>>;
/// Essentially a fiber in React
pub struct SuspenseBoundary {
pub id: ScopeId,
waiting_on: HashSet<SuspenseId>,
mutations: Vec<Mutation<'static>>,
pub waiting_on: HashSet<SuspenseId>,
pub mutations: Vec<Mutation<'static>>,
}
impl SuspenseBoundary {
@@ -28,44 +31,24 @@ impl SuspenseBoundary {
}
}
/*
many times the future will be ready every time it's polled, so we can spin on it until it doesnt wake us up immediately
*/
pub struct SuspenseLeaf {
pub id: SuspenseId,
pub scope: ScopeId,
pub scope_id: ScopeId,
pub boundary: ScopeId,
pub tx: futures_channel::mpsc::UnboundedSender<SchedulerMsg>,
pub notified: Cell<bool>,
pub task: *mut dyn Future<Output = Element<'static>>,
}
pub fn make_suspense_waker(task: &SuspenseLeaf) -> Waker {
let raw = RawWaker::new(task as *const SuspenseLeaf as *const _, task_vtable());
unsafe { Waker::from_raw(raw) }
}
fn task_vtable() -> &'static RawWakerVTable {
&RawWakerVTable::new(clone, wake, wake_by_ref, drop_task)
}
unsafe fn clone(data: *const ()) -> RawWaker {
RawWaker::new(data as *const (), task_vtable())
}
unsafe fn wake(data: *const ()) {
wake_by_ref(data);
}
unsafe fn wake_by_ref(data: *const ()) {
let task = &*(data as *const SuspenseLeaf);
task.tx
.unbounded_send(SchedulerMsg::SuspenseNotified(task.id))
.expect("Scheduler should exist");
}
unsafe fn drop_task(_data: *const ()) {
// doesnt do anything
impl RcWake for SuspenseLeaf {
fn wake_by_ref(arc_self: &Rc<Self>) {
if arc_self.notified.get() {
return;
}
arc_self.notified.set(true);
_ = arc_self
.tx
.unbounded_send(SchedulerMsg::SuspenseNotified(arc_self.id));
}
}