Revise low level fiber semantics to play nicer with schedulers.

Now that I'm starting to write a real async scheduler on top of Wren's
basic fiber API, I have a better feel for what it needs. It turns out
run() is not it.

- Remove run() methods.
- Add transfer() which leaves the caller of the invoked fiber alone.
- Add suspend() to return control to the host application.
- Add Timer.schedule() to start a new independently scheduled fiber.
- Change Timer.sleep() so that it only transfers control to explicitly
  scheduled fibers, not any one.
This commit is contained in:
Bob Nystrom
2015-08-30 22:15:37 -07:00
parent 91af02ac81
commit 556af50f83
49 changed files with 469 additions and 350 deletions
+21
View File
@@ -0,0 +1,21 @@
import "timer" for Timer
var a = Fiber.new {
IO.print("a before")
Timer.sleep(10)
IO.print("a after")
}
var b = Fiber.new {
IO.print("b before")
a.call()
IO.print("b after")
}
// All fibers are suspended since they were directly called and not scheduled.
IO.print("before") // expect: before
b.call() // expect: b before
// expect: a before
// expect: a after
// expect: b after
IO.print("done") // expect: done
+4 -4
View File
@@ -1,14 +1,14 @@
import "timer" for Timer
Fiber.new {
Timer.schedule {
Timer.sleep(2)
IO.print("a")
}.call()
}
Fiber.new {
Timer.schedule {
Timer.sleep(1)
IO.print("b")
}.call()
}
IO.print("main")
Timer.sleep(3)
+4 -4
View File
@@ -1,15 +1,15 @@
import "timer" for Timer
// These are both rounded to 1, so "a" should complete first.
Fiber.new {
Timer.schedule {
Timer.sleep(1.5)
IO.print("a")
}.call()
}
Fiber.new {
Timer.schedule {
Timer.sleep(1.3)
IO.print("b")
}.call()
}
IO.print("main")
Timer.sleep(3)
+3
View File
@@ -0,0 +1,3 @@
import "timer" for Timer
IO.print(Timer.sleep(0)) // expect: null
+16 -16
View File
@@ -1,27 +1,27 @@
import "timer" for Timer
Fiber.new {
Timer.schedule {
IO.print("a before")
Timer.sleep(0)
IO.print("a")
}.call()
IO.print("a after")
}
Fiber.new {
Timer.schedule {
IO.print("b before")
Timer.sleep(0)
IO.print("b")
}.call()
Fiber.new {
Timer.sleep(0)
IO.print("c")
}.call()
IO.print("b after")
}
IO.print("main")
Timer.sleep(0) // This is enough to let the other fiber run.
Timer.sleep(0) // This is enough to let the other fibers run to their sleep.
IO.print("main after")
Timer.sleep(0) // And now their sleeps complete.
IO.print("done")
// expect: main
// Run in the order they were enqueued.
// expect: a
// expect: b
// expect: c
// expect: a before
// expect: b before
// expect: main after
// expect: a after
// expect: b after
// expect: done