Skip to content

Commit 2105dbd

Browse files
committed
fix: event loop logic
1 parent 5e9e2f9 commit 2105dbd

File tree

4 files changed

+50
-13
lines changed

4 files changed

+50
-13
lines changed

Cargo.lock

Lines changed: 3 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ authors = ["the Andromeda team"]
77
edition = "2024"
88
license = "Mozilla Public License 2.0"
99
repository = "https://github.com/tryandromeda/andromeda"
10-
version = "0.1.0-draft46"
10+
version = "0.1.0-draft47"
1111

1212
[workspace.dependencies]
1313
andromeda-core = { path = "core" }

core/src/host_data.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -60,11 +60,11 @@ impl<UserMacroTask> HostData<UserMacroTask> {
6060
F::Output: Send + 'static,
6161
{
6262
let macro_task_count = self.macro_task_count.clone();
63-
macro_task_count.fetch_add(1, Ordering::Relaxed);
63+
macro_task_count.fetch_add(1, Ordering::Release);
6464

6565
let task_handle = tokio::spawn(async move {
6666
future.await;
67-
macro_task_count.fetch_sub(1, Ordering::Relaxed);
67+
macro_task_count.fetch_sub(1, Ordering::Release);
6868
});
6969

7070
let task_id = TaskId::from_index(self.task_count.fetch_add(1, Ordering::Relaxed));
@@ -80,7 +80,7 @@ impl<UserMacroTask> HostData<UserMacroTask> {
8080
task.abort();
8181

8282
// Manually decrease the macro tasks counter as the task was aborted.
83-
self.macro_task_count.fetch_sub(1, Ordering::Relaxed);
83+
self.macro_task_count.fetch_sub(1, Ordering::Release);
8484
}
8585

8686
/// Clear a MacroTask given it's [TaskId].
@@ -97,7 +97,7 @@ impl<UserMacroTask> HostData<UserMacroTask> {
9797
task.abort();
9898

9999
// Manually decrease the macro tasks counter as the task was aborted.
100-
self.macro_task_count.fetch_sub(1, Ordering::Relaxed);
100+
self.macro_task_count.fetch_sub(1, Ordering::Release);
101101
Ok(())
102102
}
103103

core/src/runtime.rs

Lines changed: 42 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ impl<UserMacroTask> RuntimeHostHooks<UserMacroTask> {
9595
}
9696

9797
pub fn any_pending_macro_tasks(&self) -> bool {
98-
self.host_data.macro_task_count.load(Ordering::Relaxed) > 0
98+
self.host_data.macro_task_count.load(Ordering::Acquire) > 0
9999
}
100100

101101
/// Resolve a module specifier relative to a referrer path
@@ -784,12 +784,20 @@ impl<UserMacroTask> Runtime<UserMacroTask> {
784784
});
785785
}
786786

787-
// If both the microtasks and macrotasks queues are empty we can end the event loop
788-
if !self.host_hooks.any_pending_macro_tasks() {
787+
// Try to handle a macro task without blocking
788+
// This handles the case where a task completed so fast that the counter
789+
// was already decremented but the message is still in the channel
790+
let has_macro_task = self.try_handle_macro_task();
791+
792+
// Only exit if there are no pending tasks AND no message was processed
793+
if !has_macro_task && !self.host_hooks.any_pending_macro_tasks() {
789794
break;
790795
}
791-
792-
self.handle_macro_task();
796+
797+
// If we saw pending tasks but got no message, block waiting for one
798+
if !has_macro_task && self.host_hooks.any_pending_macro_tasks() {
799+
self.handle_macro_task();
800+
}
793801
}
794802

795803
RuntimeOutput {
@@ -825,6 +833,35 @@ impl<UserMacroTask> Runtime<UserMacroTask> {
825833
_ => {}
826834
}
827835
}
836+
837+
// Try to handle a macro task without blocking, returns true if a task was handled
838+
pub fn try_handle_macro_task(&mut self) -> bool {
839+
match self.config.macro_task_rx.try_recv() {
840+
Ok(MacroTask::ResolvePromise(root_value)) => {
841+
self.agent.run_in_realm(&self.realm_root, |agent, gc| {
842+
let value = root_value.take(agent);
843+
if let Value::Promise(promise) = value {
844+
let promise_capability = PromiseCapability::from_promise(promise, false);
845+
promise_capability.resolve(agent, Value::Undefined, gc);
846+
} else {
847+
panic!("Attempted to resolve a non-promise value");
848+
}
849+
});
850+
true
851+
}
852+
// Let the user runtime handle its macro tasks
853+
Ok(MacroTask::User(e)) => {
854+
(self.config.eventloop_handler)(
855+
e,
856+
&mut self.agent,
857+
&self.realm_root,
858+
&self.host_hooks.host_data,
859+
);
860+
true
861+
}
862+
_ => false
863+
}
864+
}
828865
}
829866

830867
pub struct RuntimeOutput {

0 commit comments

Comments
 (0)