module
Lapis::Docs::D_CONCURRENCY_AND_FIBERS::A_FIBERS_AND_COOPERATIVE_AWAIT
Overview
Fibers & Cooperative Signal Awaiting
Comprehensive guide to running Crystal fibers in Godot's single-threaded scene loop, cooperative yielding, and avoiding the top-level sleep deadlock trap.
Executive Summary & Key Topics
| Topic | Method / Anchor | Description |
|---|---|---|
| The Three Golden Fiber Invariants | .topic_00_fiber_rules |
Essential rules for writing asynchronous fiber code in LibGodot. |
| Yielding Execution in _process | .topic_01_cooperative_yielding |
Pumping spawned fibers cooperatively from the engine main thread. |
| The Sleep Deadlock Hazard | .topic_02_the_sleep_deadlock_hazard |
Why sleep hangs in fibers and how to await timers safely. |
Related Guides & Source References
- Concurrency Safety:
src/libgodot/extensions/scene_tree.cr - Live Specs:
spec/thread_safety_spec.cr
Defined in:
libgodot/docs/d_concurrency_and_fibers/a_fibers_and_cooperative_await.crClass Method Summary
-
.topic_00_fiber_rules : Nil
The Three Golden Fiber Invariants: Essential rules for writing asynchronous fiber code in LibGodot.
-
.topic_01_cooperative_yielding : Nil
Yielding Execution in _process: Pumping spawned fibers cooperatively from the engine main thread.
-
.topic_02_the_sleep_deadlock_hazard : Nil
The Sleep Deadlock Hazard: Why sleep hangs in fibers and how to await timers safely.
Class Method Detail
The Three Golden Fiber Invariants: Essential rules for writing asynchronous fiber code in LibGodot.
Key Topics & Information
- Rule 1: Godot owns the OS main loop; fibers must cooperatively yield via Fiber.yield
- Rule 2: NEVER call top-level sleep in a fiber; Godot does not pump LibEvent
- Rule 3: Use await(timer) or frame delta accumulators for time delays
Yielding Execution in _process: Pumping spawned fibers cooperatively from the engine main thread.
Because Godot controls the OS event loop, spawned fibers (spawn do ... end) will starve unless the main thread cooperatively yields:
node GameManager < Node do
def _ready : Void
# Spawn a background gameplay fiber
spawn do
Godot.print("Dialog sequence started!")
await(get_tree.create_timer(2.0))
Godot.print("2 seconds elapsed non-blockingly!")
end
end
def _process(delta : Float64) : Void
# Cooperatively yield time slice to pending fibers:
Fiber.yield
end
end
The Sleep Deadlock Hazard: Why sleep hangs in fibers and how to await timers safely.
The Hazard:
In standard Crystal console programs, sleep 2.seconds registers a timer with Crystal's LibEvent / IOCP event loop. In LibGodot, Godot drives the main loop — not LibEvent! Calling top-level sleep suspends the fiber permanently, hanging that fiber indefinitely.
The Safe Pattern:
Always use Godot's timer mechanism with await:
# SAFE: Suspends fiber until Godot's timer fires
await(get_tree.create_timer(1.5))