Skip to content

Coroutine Demo

App: apps/coroutine_demo/

Demonstrates cooperative coroutines (engine PLM-031 / ADR 0037): two Async.run coroutines sequence themselves every frame with no per-frame timer code. One cycles a traffic light on its own schedule with Async.wait; the other counts frames with Async.nextFrame. The engine resumes both automatically each frame — the game wires nothing into its own update.

Terminal window
% ./plume3d coroutine_demo

A small GUI window shows the current light, the elapsed frame count, and the number of pending coroutines.

  • On init, starts two coroutines with Async.run { ... }. Each is a zero-arg block the engine resumes every frame until it suspends.
  • Coroutine 1 — the traffic light. An infinite while (true) loop that sets the light to GREEN, Async.wait(3.0), YELLOW, Async.wait(1.0), RED, Async.wait(3.0), and repeats. The wait calls sequence the phases in scene time — the loop reads as a plain schedule instead of a hand-rolled timer and state machine.
  • Coroutine 2 — the frame counter. An infinite loop that increments a counter and calls Async.nextFrame(), so it advances exactly once per frame.
  • In update, draws a Gui window with the current light, the frame count, and Async.pending (the number of suspended coroutines — 2 here, since both loop forever and are always waiting). No coroutine is ticked by the game; the engine’s auto-tick resumes them.
import "engine" for Async
// A self-sequencing loop — the wait() calls pace it; no per-frame timer bookkeeping.
Async.run {
while (true) {
_light = "GREEN"
Async.wait(3.0)
_light = "YELLOW"
Async.wait(1.0)
_light = "RED"
Async.wait(3.0)
}
}
// One resume per frame.
Async.run {
while (true) {
_frames = _frames + 1
Async.nextFrame()
}
}

Both coroutines never return, so Async.pending stays at 2 for the life of the app — the scheduler is holding two suspended fibers and resuming each when its wake time is due.

  • CoroutinesAsync.run, Async.wait, Async.nextFrame, Async.pending.
  • Gui — the status window (beginWindow, layoutRowDynamic, label).