Coroutines in Lua
Coroutines are a powerful feature in Lua that allow for cooperative multitasking. Unlike threads in other languages, coroutines are not preemptive - they yield control voluntarily.
Basic Coroutine Operations
Creating and running a coroutine:
-- Create a coroutine
local co = coroutine.create(function()
print("Hello from coroutine")
end)
-- Run the coroutine
coroutine.resume(co)
Yielding and Resuming
Coroutines can yield control and later be resumed:
local co = coroutine.create(function()
print("First")
coroutine.yield()
print("Second")
end)
coroutine.resume(co) -- Prints "First"
coroutine.resume(co) -- Prints "Second"
Passing Values
You can pass values between yield and resume:
local co = coroutine.create(function(a, b)
print("Received:", a, b)
local sum = a + b
sum = coroutine.yield(sum)
print("Received after yield:", sum)
return sum * 2
end)
-- First resume (starts the coroutine)
local _, initialSum = coroutine.resume(co, 2, 3)
print("Yielded sum:", initialSum) -- 5
-- Second resume (after yield)
local _, finalResult = coroutine.resume(co, initialSum * 10)
print("Final result:", finalResult) -- 100
Coroutine Status
Check a coroutine's status with coroutine.status
:
print(coroutine.status(co)) -- "suspended", "running", or "dead"
Producer-Consumer Pattern
A common use of coroutines is implementing producer-consumer patterns:
function producer()
local i = 0
return function()
i = i + 1
coroutine.yield(i)
end
end
local prod = producer()
local co = coroutine.create(function()
while true do
prod()
end
end)
-- Consumer
for i = 1, 5 do
coroutine.resume(co)
print(coroutine.status(co), select(2, coroutine.resume(co)))
end
Coroutines vs Threads
Key differences between coroutines and threads:
- Coroutines are cooperative (must yield explicitly)
- Only one coroutine runs at a time
- No need for locks or synchronization
- Much lighter weight than OS threads
Asynchronous Programming
Coroutines are often used with event loops for async programming:
-- Pseudocode for async I/O with coroutines
function async_read(file)
local co = coroutine.running()
register_callback(function(data)
coroutine.resume(co, data)
end)
return coroutine.yield()
end
-- Usage in a coroutine
coroutine.create(function()
local data = async_read("file.txt")
print("Received data:", data)
end)
Next Steps
Now that you understand coroutines, learn about error handling in Lua.