Merge pull request #1710 from Exotik850/cx-spawn-poll

Make cx.spawn poll the task before returning `TaskId`
This commit is contained in:
Jonathan Kelley authored and GitHub committed 2024-01-04 10:07:22 -08:00
commit 1d289ff282
3 files changed
+20 -24

No files matched your search

+1 -7
View File
@@ -27,13 +27,7 @@ fn app(cx: Scope) -> Element {
button { button {
onclick: move |_| { onclick: move |_| {
let dom = VirtualDom::new_with_props(compose, ComposeProps { let dom = VirtualDom::new_with_props(compose, ComposeProps { app_tx: tx.clone() });
app_tx: tx.clone()
});
// this returns a weak reference to the other window
// Be careful not to keep a strong reference to the other window or it will never be dropped
// and the window will never close.
window.new_window(dom, Default::default()); window.new_window(dom, Default::default());
}, },
"Click to compose a new email" "Click to compose a new email"
+11 -7
View File
@@ -19,7 +19,7 @@ pub struct TaskId(pub usize);
/// the task itself is the waker /// the task itself is the waker
pub(crate) struct LocalTask { pub(crate) struct LocalTask {
pub scope: ScopeId, pub scope: ScopeId,
pub(super) task: RefCell<Pin<Box<dyn Future<Output = ()> + 'static>>>, pub task: RefCell<Pin<Box<dyn Future<Output = ()> + 'static>>>,
pub waker: Waker, pub waker: Waker,
} }
@@ -48,11 +48,15 @@ impl Scheduler {
})), })),
}; };
entry.insert(task); let mut cx = std::task::Context::from_waker(&task.waker);
self.sender if !task.task.borrow_mut().as_mut().poll(&mut cx).is_ready() {
.unbounded_send(SchedulerMsg::TaskNotified(task_id)) self.sender
.expect("Scheduler should exist"); .unbounded_send(SchedulerMsg::TaskNotified(task_id))
.expect("Scheduler should exist");
}
entry.insert(task);
task_id task_id
} }
@@ -60,8 +64,8 @@ impl Scheduler {
/// Drop the future with the given TaskId /// Drop the future with the given TaskId
/// ///
/// This does not abort the task, so you'll want to wrap it in an aborthandle if that's important to you /// This does not abort the task, so you'll want to wrap it in an aborthandle if that's important to you
pub fn remove(&self, id: TaskId) { pub fn remove(&self, id: TaskId) -> Option<LocalTask> {
self.tasks.borrow_mut().try_remove(id.0); self.tasks.borrow_mut().try_remove(id.0)
} }
} }
+8 -10
View File
@@ -99,9 +99,8 @@ where
// Create the new future // Create the new future
let return_value = future(dependencies.out()); let return_value = future(dependencies.out());
if let Some(task) = return_value.apply(state.cleanup.clone(), cx) { let task = return_value.apply(state.cleanup.clone(), cx);
state.task.set(Some(task)); state.task.set(Some(task));
}
} }
} }
@@ -109,15 +108,15 @@ type UseEffectCleanup = Rc<RefCell<Option<Box<dyn FnOnce()>>>>;
/// Something that can be returned from a `use_effect` hook. /// Something that can be returned from a `use_effect` hook.
pub trait UseEffectReturn<T> { pub trait UseEffectReturn<T> {
fn apply(self, oncleanup: UseEffectCleanup, cx: &ScopeState) -> Option<TaskId>; fn apply(self, oncleanup: UseEffectCleanup, cx: &ScopeState) -> TaskId;
} }
impl<T> UseEffectReturn<()> for T impl<T> UseEffectReturn<()> for T
where where
T: Future<Output = ()> + 'static, T: Future<Output = ()> + 'static,
{ {
fn apply(self, _: UseEffectCleanup, cx: &ScopeState) -> Option<TaskId> { fn apply(self, _: UseEffectCleanup, cx: &ScopeState) -> TaskId {
Some(cx.push_future(self)) cx.push_future(self)
} }
} }
@@ -128,12 +127,11 @@ where
T: Future<Output = F> + 'static, T: Future<Output = F> + 'static,
F: FnOnce() + 'static, F: FnOnce() + 'static,
{ {
fn apply(self, oncleanup: UseEffectCleanup, cx: &ScopeState) -> Option<TaskId> { fn apply(self, oncleanup: UseEffectCleanup, cx: &ScopeState) -> TaskId {
let task = cx.push_future(async move { cx.push_future(async move {
let cleanup = self.await; let cleanup = self.await;
*oncleanup.borrow_mut() = Some(Box::new(cleanup) as Box<dyn FnOnce()>); *oncleanup.borrow_mut() = Some(Box::new(cleanup) as Box<dyn FnOnce()>);
}); })
Some(task)
} }
} }