Suspending and resuming execution

An ordinary function normally runs until it returns a result to its caller. A coroutine can suspend partway through, preserving local state and an execution position for later resumption. A producer can consequently yield one item at a time instead of building an entire collection before its consumer starts work.

References: [1] [2]

Yielding and resuming cooperatively

Lua creates a coroutine separately from starting it, resumes it through resume, and suspends it explicitly through yield. Creation is not execution, and suspension is not final termination. This cooperative arrangement makes switching points part of the program’s control rules, unlike treating every coroutine as a preemptively scheduled operating-system thread.

References: [1]

Exchanging values across suspension

Suspension can exchange information in both directions. Lua accepts values when resuming a coroutine, while Python’s PEP 342 adds generator operations such as send, exception injection, and closure. These mechanisms support richer control flow, but languages differ in suspension across call boundaries and in the cleanup behavior attached to termination.

References: [1] [2]

Scheduling is a separate responsibility

Coroutines can organize pipelines and asynchronous work, but a program or framework must decide when to resume them, limit outstanding tasks, and handle cancellation. A long-running coroutine that never yields can prevent peers from progressing on one scheduling thread. Calling blocking code does not automatically become nonblocking because the caller is a coroutine.

References: [1] [2]