Lua - Chaining Coroutines using Scheduler
Using Scheduler to Chain coroutines if implemented correctly is a more organized approach. We can create a specialized Schduler coroutine whose purpose is to manage the execution and switching between coroutines. It will help in complex control flows and data movements.
Example - Chaining Using a Schduler Coroutine
A scheduler will manage creation, yielding and resuming process of coroutines as shown below:
Define coroutines
-- function to represent coroutine1
function coroutine1(data)
print("Coroutine #1 started with:", data)
-- yield the current coroutine and signal to switch to next coroutine
coroutine.yield("Coroutine #1 Done", data * 2)
print("Coroutine #1 Done.")
end
-- function to represent coroutine2
function coroutine2(data)
print("Coroutine #2 started with:", data)
-- yield the current coroutine and signal to switch to next coroutine
coroutine.yield("Coroutine #2 Done", data * 5)
print("Coroutine #2 Done")
end
Create Scheduler
function scheduler()
-- create coroutines with initial data
local tasks = {
coroutine.create(coroutine1, 1),
coroutine.create(coroutine2, 2)
}
-- task results
local task_results = { 1 }
-- if there are tasks in the tasks table
while #tasks > 0 do
-- get the first coroutine
local co = table.remove(tasks, 1)
-- start the coroutine and get the result
local status, yield_type, yield_value = coroutine.resume(co, table.remove(task_results, 1))
-- if coroutine is executed successfully
if status then
print("Scheduler received:", yield_type, yield_value)
if yield_type == "Coroutine #1 Done" then
table.insert(task_results, yield_value + 1)
elseif yield_type == "Coroutine #2 Done" then
table.insert(task_results, yield_value * 3)
end
else
print("Task finished or errored.", status)
end
end
print("All tasks processed.")
end
Complete Example - Chaining coroutines
main.lua
-- function to represent coroutine1
function coroutine1(data)
print("Coroutine #1 started with:", data)
-- yield the current coroutine and signal to switch to next coroutine
coroutine.yield("Coroutine #1 Done", data * 2)
print("Coroutine #1 Done.")
end
-- function to represent coroutine2
function coroutine2(data)
print("Coroutine #2 started with:", data)
-- yield the current coroutine and signal to switch to next coroutine
coroutine.yield("Coroutine #2 Done", data * 5)
print("Coroutine #2 Done")
end
function scheduler()
-- create coroutines with initial data
local tasks = {
coroutine.create(coroutine1, 1),
coroutine.create(coroutine2, 2)
}
-- task results
local task_results = { 1 }
-- if there are tasks in the tasks table
while #tasks > 0 do
-- get the first coroutine
local co = table.remove(tasks, 1)
-- start the coroutine and get the result
local status, yield_type, yield_value = coroutine.resume(co, table.remove(task_results, 1))
-- if coroutine is executed successfully
if status then
print("Scheduler received:", yield_type, yield_value)
if yield_type == "Coroutine #1 Done" then
table.insert(task_results, yield_value + 1)
elseif yield_type == "Coroutine #2 Done" then
table.insert(task_results, yield_value * 3)
end
else
print("Task finished or errored.", status)
end
end
print("All tasks processed.")
end
-- create and start the scheduler coroutine
coroutine.resume(coroutine.create(scheduler))
Output
When we run the above code, we will get the following output−
Coroutine #1 started with: 1 Scheduler received: Coroutine #1 Done 2 Coroutine #2 started with: 3 Scheduler received: Coroutine #2 Done 15 All tasks processed.
Explanation
Here scheduler coroutine maintains a list of other corountines.
Scheduler iterates through each coroutine and resume them.
Each coroutine yield a message as type and a value.
Scheduler interprets the type and decide the next action.
Advertisements