A coroutine is an independently suspended execution path with its own stack, local variables, and instruction pointer. Coroutines share the Lua state’s global data, but only one runs at a time. Switching is cooperative rather than preemptive.
Create, resume, and yield
1 | local co = coroutine.create(function(a, b) |
The first resume supplies the function arguments. Values passed to yield return from resume; values in the next resume become the result of that yield. Final return values come back from the last resume.
A coroutine may be suspended, running, normal, or dead. Always check the first value returned by resume, because it reports whether execution succeeded.
Coroutines as iterators
coroutine.wrap returns a function that resumes the coroutine and either returns yielded values or raises an error:
1 | local function permutations(items) |
The generator retains its local state naturally, avoiding a manually constructed state machine.
Who owns the main loop?
Coroutines can invert control between a producer and consumer, or let sequential-looking code pause until an event loop has data. This resolves the architectural question of which component owns the main loop.
They do not create parallel execution or turn blocking calls into asynchronous ones. Pair them with nonblocking APIs for scalable I/O, and use threads or processes when work must execute on multiple CPU cores.