Wrenlift

Fiber

Cooperative coroutines. Fiber.new {} creates a suspended one; .call runs it until it yields, returns, or aborts. .try is the same as .call but returns rejections instead of propagating them.

Construct & identity

MethodWhat it does
Fiber.new(body)Wrap a closure as a new suspended fiber.
Fiber.currentThe fiber that's currently running.
.isDonetrue when the fiber has returned (or aborted).
var f = Fiber.new {
  System.print("inside")
}
f.call()        // inside
f.isDone        // true

Yield & resume

MethodWhat it does
.call() · .call(value)Resume the fiber. Returns the value the fiber yielded or returned.
Fiber.yield() · Fiber.yield(v)Yield to the caller. Stays alive; the caller's .call returns v (or null).
Fiber.suspend()Suspend the running fiber's enclosing transfer (rarely needed directly; used by async bridges).
Fiber.abort(error)Abort the fiber. Up the stack, .try { ... } catches it as the fiber's .error slot.
var counter = Fiber.new {
  var i = 0
  while (true) {
    Fiber.yield(i)
    i = i + 1
  }
}
System.print(counter.call())    // 0
System.print(counter.call())    // 1
System.print(counter.call())    // 2

.call vs .try

.call propagates aborts up the parent stack. .try swallows them and returns the error value instead, so the parent can decide how to react.

var fragile = Fiber.new { Fiber.abort("nope") }

var r = fragile.try()
System.print(fragile.error)     // "nope"
System.print(r)                 // null

Cancellation & deadlines

MethodWhat it does
Fiber.isCancelledtrue when an external caller has requested cancellation.
Fiber.cancel()Mark this fiber for cancellation. Compute loops can poll Fiber.isCancelled and bail.
Fiber.deadlineMsDeadline in milliseconds (host-monotonic), or null if none set.
Fiber.setDeadlineMs(ms)Set the deadline. Runtime checkpoints inside loops poll this; expiring deadlines surface as aborts.
var work = Fiber.new {
  while (!Fiber.isCancelled) {
    step()
  }
}
work.call()

Scheduler

When many fibers wait on timers or on each other, let the built-in scheduler run them instead of calling each one by hand.

MethodWhat it does
Fiber.spawn(fn)Hand a fiber to the scheduler. It runs a turn at a time. If it aborts, the task ends and the error stays in its .error. Returns the fiber.
Fiber.tick(ms)Give every ready task a turn. Keep going while tasks are ready and ms has not passed; 0 means one round. Returns true while tasks remain.
Fiber.idle(ms)Block until a task is ready, a timer is due, a wake arrives, or ms passes.
Fiber.sleep(ms)Inside a task, park on a timer while the other tasks run. At module top level, run the scheduler until the time is up.
Fiber.waiter · Fiber.park(token, ms) · Fiber.wake(token)A wait token you use once. park returns true when woken and false on timeout. wake works from any thread.
Fiber.liveTasks not yet finished.
Fiber.spawn {
  Fiber.sleep(30)          // a timer park; the others run meanwhile
  System.print("a")
}
Fiber.spawn {
  Fiber.yield()            // let the other tasks have a turn
  System.print("b")
}
while (Fiber.tick(0)) Fiber.idle(100)   // prints b, then a

A task is still a fiber, and it runs on the thread that made it. To run tasks in parallel on other threads, or in a separate VM, see Concurrency.

Async-bridge integration

Browser bridges — Browser.fetch, Browser.setTimeout, Dom.*, WebSocket.* — return a Future. Calling .await on a future inside a fiber suspends it through Fiber.suspend; the host scheduler resumes it via .call(value) when the future settles.

var page = Fiber.new {
  var html = Browser.fetch("https://example.com").await
  System.print(html.count)
}
page.try()

See Future for the settled-value shape and the difference between Future and ByteFuture.