Lua Producer Consumer Coroutines
A producer consumer pair is a coroutine that makes values and a caller that takes them one at a time. Each resume asks for the next value and each yield hands one value back.
A producer hands out one value per resume
The producer yields three numbers and then ends. Four resumes take each value in turn.
local producer = coroutine.create(function()
coroutine.yield(10)
coroutine.yield(20)
coroutine.yield(30)
end)
local ok, value = coroutine.resume(producer)
print(ok, value)
local ok2, value2 = coroutine.resume(producer)
print(ok2, value2)
local ok3, value3 = coroutine.resume(producer)
print(ok3, value3)
local ok4 = coroutine.resume(producer)
print(ok4)Values can travel in both directions
The producer first yields the word ready. The next resume sends 5 and the producer yields 15.
local co = coroutine.create(function()
local got = coroutine.yield("ready")
coroutine.yield(got + 10)
end)
local ok, value = coroutine.resume(co)
print(ok, value)
local ok2, value2 = coroutine.resume(co, 5)
print(ok2, value2)A loop can take every value until the producer ends
The loop resumes while the producer is not dead. It prints each yielded square and stops at the end.
local co = coroutine.create(function()
for i = 1, 3 do
coroutine.yield(i * i)
end
end)
while coroutine.status(co) ~= "dead" do
local ok, value = coroutine.resume(co)
if value then
print(value)
end
endExample
local producer = coroutine.create(function()
local step = coroutine.yield("start")
for n = 1, 3 do
coroutine.yield(n * step)
end
return "done"
end)
local ok, value = coroutine.resume(producer)
print(ok, value)
local ok2, value2 = coroutine.resume(producer, 10)
print(ok2, value2)
local ok3, value3 = coroutine.resume(producer)
print(ok3, value3)
local ok4, value4 = coroutine.resume(producer)
print(ok4, value4)
local ok5, value5 = coroutine.resume(producer)
print(ok5, value5)Key points
- Producer: the producer is the coroutine body that yields each value in turn.
- Consumer: the consumer is the caller that resumes the coroutine to get each value.
- Yield: yield pauses the producer and hands a value to the consumer.
- Send: a value passed to resume becomes the result of yield inside the producer.
- Return: the last resume returns true plus the return value when the producer finishes.
In this example, the first resume starts the producer and takes the word start. The second resume sends 10 as the step and takes the first product. Later resumes take 20 and 30, and the last resume takes the return word done.
Note
the consumer checks the first resume result before it uses a yielded value.
Try it Yourself
Edit the code, then press Run.
Running is simulated
Exercise
The producer yields a value and waits. What does the next resume argument become inside the producer?