feat: replace fiber run() with transfer() and suspend() for scheduler-friendly semantics
Remove the run() method from fibers and introduce transfer() for non-stack-based fiber switching, along with suspend() to pause the interpreter and return control to the host application. Update Timer.sleep() to use runNextScheduled_() instead of Fiber.yield(), and add Timer.schedule() for creating independently scheduled fibers. Refactor the core fiber runtime to support transfer semantics, including proper error handling for aborted fibers and self-transfer edge cases. Fix a missing quote in test.py's runtime error validation string.
This commit is contained in:
+23
-3
@@ -14,16 +14,36 @@ static const char* timerLibSource =
|
||||
" if (!(milliseconds is Num)) Fiber.abort(\"Milliseconds must be a number.\")\n"
|
||||
" if (milliseconds < 0) Fiber.abort(\"Milliseconds cannot be negative.\")\n"
|
||||
" startTimer_(milliseconds, Fiber.current)\n"
|
||||
" Fiber.yield()\n"
|
||||
"\n"
|
||||
" runNextScheduled_()\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" // TODO: Once the CLI modules are more fleshed out, find a better place to\n"
|
||||
" // put this.\n"
|
||||
" static schedule(callable) {\n"
|
||||
" if (__scheduled == null) __scheduled = []\n"
|
||||
" __scheduled.add(Fiber.new {\n"
|
||||
" callable.call()\n"
|
||||
" runNextScheduled_()\n"
|
||||
" })\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" foreign static startTimer_(milliseconds, fiber)\n"
|
||||
"\n"
|
||||
" // Called by native code.\n"
|
||||
" static resumeTimer_(fiber) {\n"
|
||||
" fiber.run()\n"
|
||||
" fiber.transfer()\n"
|
||||
" }\n"
|
||||
"}\n";
|
||||
"\n"
|
||||
" static runNextScheduled_() {\n"
|
||||
" if (__scheduled == null || __scheduled.isEmpty) {\n"
|
||||
" Fiber.suspend()\n"
|
||||
" } else {\n"
|
||||
" __scheduled.removeAt(0).transfer()\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
"}\n"
|
||||
"\n";
|
||||
|
||||
// The Wren method to call when a timer has completed.
|
||||
static WrenMethod* resumeTimer;
|
||||
|
||||
+22
-2
@@ -3,13 +3,33 @@ class Timer {
|
||||
if (!(milliseconds is Num)) Fiber.abort("Milliseconds must be a number.")
|
||||
if (milliseconds < 0) Fiber.abort("Milliseconds cannot be negative.")
|
||||
startTimer_(milliseconds, Fiber.current)
|
||||
Fiber.yield()
|
||||
|
||||
runNextScheduled_()
|
||||
}
|
||||
|
||||
// TODO: Once the CLI modules are more fleshed out, find a better place to
|
||||
// put this.
|
||||
static schedule(callable) {
|
||||
if (__scheduled == null) __scheduled = []
|
||||
__scheduled.add(Fiber.new {
|
||||
callable.call()
|
||||
runNextScheduled_()
|
||||
})
|
||||
}
|
||||
|
||||
foreign static startTimer_(milliseconds, fiber)
|
||||
|
||||
// Called by native code.
|
||||
static resumeTimer_(fiber) {
|
||||
fiber.run()
|
||||
fiber.transfer()
|
||||
}
|
||||
|
||||
static runNextScheduled_() {
|
||||
if (__scheduled == null || __scheduled.isEmpty) {
|
||||
Fiber.suspend()
|
||||
} else {
|
||||
__scheduled.removeAt(0).transfer()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user