Fix effects triggered from async tasks; improve work scheduling docs (#2370)

* outline work scheduling

* move scheduling code from dirty_scope to scheduler

* introduce queue_effect

* Run effects after all tasks are polled if there are no components rerendered

* add a new test for async effects
This commit is contained in:
Evan Almloff authored and GitHub committed 2024-05-04 15:30:13 +01:00
1 parent 05eaca320f
commit 5290b658fd
11 files changed
+305 -53

No files matched your search

+19
View File
@@ -1,3 +1,4 @@
use crate::innerlude::Effect;
use crate::{
innerlude::{LocalTask, SchedulerMsg},
render_signal::RenderSignal,
@@ -5,6 +6,7 @@ use crate::{
scopes::ScopeId,
Task,
};
use std::collections::BTreeSet;
use std::{
cell::{Cell, Ref, RefCell},
rc::Rc,
@@ -36,6 +38,9 @@ pub struct Runtime {
// Synchronous tasks need to be run after the next render. The virtual dom stores a list of those tasks to send a signal to them when the next render is done.
pub(crate) render_signal: RenderSignal,
// The effects that need to be run after the next render
pub(crate) pending_effects: RefCell<BTreeSet<Effect>>,
}
impl Runtime {
@@ -49,6 +54,7 @@ impl Runtime {
current_task: Default::default(),
tasks: Default::default(),
suspended_tasks: Default::default(),
pending_effects: Default::default(),
})
}
@@ -150,6 +156,19 @@ impl Runtime {
pub(crate) fn with_scope<R>(scope: ScopeId, f: impl FnOnce(&Scope) -> R) -> Option<R> {
Self::with(|rt| rt.get_state(scope).map(|sc| f(&sc))).flatten()
}
/// Finish a render. This will mark all effects as ready to run and send the render signal.
pub(crate) fn finish_render(&self) {
// If there are new effects we can run, send a message to the scheduler to run them (after the renderer has applied the mutations)
if !self.pending_effects.borrow().is_empty() {
self.sender
.unbounded_send(SchedulerMsg::EffectQueued)
.expect("Scheduler should exist");
}
// And send the render signal
self.render_signal.send();
}
}
/// A guard for a new runtime. This must be used to override the current runtime when importing components from a dynamic library that has it's own runtime.