Lua - Chaining Coroutines using Queue
Using Queue can greatly simplify the coroutine chaining and make them loose coupled as well. One coroutine can send a message to the queue while another coroutine can wait on the queue to read the message and act accordingly.
Example - Chaining Using a Queue
A queue will act as channel for messages between coroutines as shown below:
Define a queue and send/receive operations
-- queue as empty table
local queue = {}
-- send message will add a message to the queue
function send(message)
table.insert(queue, message)
end
-- to receive a message from Queue
function receive()
-- if queue has message
if #queue > 0 then
-- remove first entry and return the same
return table.remove(queue, 1)
end
-- yield the current coroutine if queue is empty
return coroutine.yield()
end
Create Producer and Consumer Coroutines Functions
function Producer()
print("Producer Coroutine started")
send("Message 1 from producer")
coroutine.yield() -- yield the producer coroutine
send("Message 2 from producer")
print("Producer Coroutine finished")
end
function Consumer()
print("Consumer started")
local msg = receive() -- receive a message from queue
print("Consumer received:", msg)
coroutine.yield() -- yield the consumer coroutine
msg = receive() -- receive a message from queue
print("Consumer received:", msg)
print("Consumer Coroutine finished")
end
Create Producer and Consumer Coroutines and start them
-- create producer producer = coroutine.create(Producer) -- create consumer consumer = coroutine.create(Consumer) -- start producer coroutine.resume(producer) -- start consumer coroutine.resume(consumer) -- resume producer coroutine.resume(producer) -- resume consumer coroutine.resume(consumer)
Complete Example - Chaining coroutines
main.lua
-- queue as empty table
local queue = {}
-- send message will add a message to the queue
function send(message)
table.insert(queue, message)
end
-- to receive a message from Queue
function receive()
-- if queue has message
if #queue > 0 then
-- remove first entry and return the same
return table.remove(queue, 1)
end
-- yield the current coroutine if queue is empty
return coroutine.yield()
end
function Producer()
print("Producer Coroutine started")
send("Message 1 from producer")
coroutine.yield() -- yield the producer coroutine
send("Message 2 from producer")
print("Producer Coroutine finished")
end
function Consumer()
print("Consumer started")
local msg = receive() -- receive a message from queue
print("Consumer received:", msg)
coroutine.yield() -- yield the consumer coroutine
msg = receive() -- receive a message from queue
print("Consumer received:", msg)
print("Consumer Coroutine finished")
end
-- create producer
producer = coroutine.create(Producer)
-- create consumer
consumer = coroutine.create(Consumer)
-- start producer
coroutine.resume(producer)
-- start consumer
coroutine.resume(consumer)
-- resume producer
coroutine.resume(producer)
-- resume consumer
coroutine.resume(consumer)
Output
When we run the above code, we will get the following output−
Producer Coroutine started Consumer started Consumer received: Message 1 from producer Producer Coroutine finished Consumer received: Message 2 from producer Consumer Coroutine finished
Explanation
Here send() function sends message to the queue.
receive() function retrieves message from the queue, yields the coroutine if queue is empty.
Producer and Consumer coroutines are communicating via the queue.
Advertisements