fix: micro tasks not handled properly

This commit is contained in:
TopchetoEU 2023-11-25 18:58:35 +02:00
parent b127aadcf6
commit 4b1ec671e2
Signed by: topchetoeu
GPG Key ID: 6531B8583E5F6ED4

View File

@ -2,7 +2,7 @@ package me.topchetoeu.jscript.engine;
import java.util.HashMap;
import java.util.TreeSet;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.PriorityBlockingQueue;
import me.topchetoeu.jscript.Filename;
import me.topchetoeu.jscript.Location;
@ -35,18 +35,25 @@ public class Engine implements DebugController {
}
}
private static class Task {
private static class Task implements Comparable<Task> {
public final FunctionValue func;
public final Object thisArg;
public final Object[] args;
public final DataNotifier<Object> notifier = new DataNotifier<>();
public final Context ctx;
public final boolean micro;
public Task(Context ctx, FunctionValue func, Object thisArg, Object[] args) {
public Task(Context ctx, FunctionValue func, Object thisArg, Object[] args, boolean micro) {
this.ctx = ctx;
this.func = func;
this.thisArg = thisArg;
this.args = args;
this.micro = micro;
}
@Override
public int compareTo(Task other) {
return Integer.compare(this.micro ? 0 : 1, other.micro ? 0 : 1);
}
}
@ -62,8 +69,7 @@ public class Engine implements DebugController {
private DebugController debugger;
private Thread thread;
private LinkedBlockingDeque<Task> macroTasks = new LinkedBlockingDeque<>();
private LinkedBlockingDeque<Task> microTasks = new LinkedBlockingDeque<>();
private PriorityBlockingQueue<Task> tasks = new PriorityBlockingQueue<>();
public boolean attachDebugger(DebugController debugger) {
if (!debugging || this.debugger != null) return false;
@ -91,18 +97,12 @@ public class Engine implements DebugController {
}
}
public void run(boolean untilEmpty) {
while (!untilEmpty || !macroTasks.isEmpty()) {
while (!untilEmpty || !tasks.isEmpty()) {
try {
runTask(macroTasks.take());
while (!microTasks.isEmpty()) {
runTask(microTasks.take());
}
runTask(tasks.take());
}
catch (InterruptedException | InterruptException e) {
for (var msg : macroTasks) {
msg.notifier.error(new InterruptException(e));
}
for (var msg : tasks) msg.notifier.error(new InterruptException(e));
break;
}
}
@ -127,9 +127,8 @@ public class Engine implements DebugController {
}
public Awaitable<Object> pushMsg(boolean micro, Context ctx, FunctionValue func, Object thisArg, Object ...args) {
var msg = new Task(ctx == null ? new Context(this) : ctx, func, thisArg, args);
if (micro) microTasks.addLast(msg);
else macroTasks.addLast(msg);
var msg = new Task(ctx == null ? new Context(this) : ctx, func, thisArg, args, micro);
tasks.add(msg);
return msg.notifier;
}
public Awaitable<Object> pushMsg(boolean micro, Context ctx, Filename filename, String raw, Object thisArg, Object ...args) {