Lua Coroutine Channels
A coroutine channel is a shared queue that carries messages between coroutines. One coroutine puts a value into the queue and another coroutine takes values out of it in order.
A queue keeps first-in first-out order
Insert three values, then remove them from the front. They come out in the order they went in.
local q = {}
table.insert(q, "red")
table.insert(q, "green")
table.insert(q, "blue")
print(table.remove(q, 1))
print(table.remove(q, 1))
print(table.remove(q, 1))A sender coroutine fills the queue
The sender inserts one value and then yields. The main code resumes it again for the next value.
local q = {}
local sender = coroutine.create(function()
for _, v in ipairs({10, 20, 30}) do
table.insert(q, v)
coroutine.yield()
end
end)
coroutine.resume(sender)
coroutine.resume(sender)
coroutine.resume(sender)
print(q[1])
print(q[2])
print(q[3])A receiver coroutine drains the queue
The receiver takes one value per resume. It prints each value as it takes it.
local q = {"a", "b", "c"}
local receiver = coroutine.create(function()
while #q > 0 do
print(table.remove(q, 1))
coroutine.yield()
end
end)
coroutine.resume(receiver)
coroutine.resume(receiver)
coroutine.resume(receiver)Example
local q = {}
local sender = coroutine.create(function()
for _, v in ipairs({10, 20, 30}) do
table.insert(q, v)
coroutine.yield()
end
end)
local receiver = coroutine.create(function()
for _ = 1, 3 do
while #q == 0 do
coroutine.yield()
end
print(table.remove(q, 1))
coroutine.yield()
end
end)
for _ = 1, 3 do
coroutine.resume(sender)
coroutine.resume(receiver)
endKey points
- Channel: a shared table used as a queue for passing messages.
- Send: put a value at the back of the queue with table.insert.
- Receive: take the value at the front of the queue with table.remove.
- Order: values leave the queue in the same order they entered it.
- Sharing: both coroutines hold the same queue table, so a value sent by one is visible to the other.
In this example, the sender inserts 10, then 20, then 30, yielding after each insert. The receiver waits until the queue is not empty, removes the front value, and prints it. The main loop resumes the sender and then the receiver three times, so the values arrive in the order 10, 20, 30.
Note
Lua has no built-in channel type, so a plain table queue is the channel here.
Try it Yourself
Edit the code, then press Run.
Running is simulated
Exercise
A queue holds 5, then 9, then 2. What does table.remove(q, 1) return on the first call?