Lua Coroutine Timeouts
A cooperative timeout is a deadline a scheduler enforces with a simulated tick counter. The scheduler advances the counter itself, and it stops resuming a task once the counter passes the task deadline.
A tick counter advances each round
The scheduler adds one to the tick on every round and prints it. The count is fully predictable.
local tick = 0
for _ = 1, 3 do
tick = tick + 1
print(tick)
endA task past its deadline times out
The task needs five steps but its deadline is tick 3. The scheduler stops at tick 3 and reports the timeout.
local tick = 0
local deadline = 3
local task = coroutine.create(function()
for i = 1, 5 do
print("step " .. i)
coroutine.yield()
end
end)
while coroutine.status(task) ~= "dead" do
tick = tick + 1
if tick > deadline then
print("timed out")
break
end
coroutine.resume(task)
endA task inside its deadline finishes
This task needs two steps and its deadline is tick 3. It finishes on tick 2, before any timeout.
local tick = 0
local deadline = 3
local task = coroutine.create(function()
for i = 1, 2 do
print("step " .. i)
coroutine.yield()
end
end)
while coroutine.status(task) ~= "dead" do
tick = tick + 1
if tick > deadline then
print("timed out")
break
end
coroutine.resume(task)
end
print("done")Example
local function run(task, deadline)
local tick = 0
while coroutine.status(task) ~= "dead" do
tick = tick + 1
if tick > deadline then
print("timed out at tick " .. tick)
return
end
coroutine.resume(task)
end
print("finished at tick " .. tick)
end
local slow = coroutine.create(function()
for i = 1, 5 do
print("slow step " .. i)
coroutine.yield()
end
end)
local fast = coroutine.create(function()
for i = 1, 2 do
print("fast step " .. i)
coroutine.yield()
end
end)
run(slow, 3)
run(fast, 3)Key points
- Tick: a counter the scheduler advances by one on each round, standing in for passing time.
- Deadline: the tick value by which a task must finish.
- Timeout: what happens when the tick passes a task deadline before the task finishes.
- Cooperative: the task only stops at a yield, since the scheduler cannot interrupt it mid-step.
- Check point: the scheduler compares the tick with each deadline before every resume.
In this example, each run keeps its own tick counter and a deadline of 3. The slow task prints three steps, then tick 4 passes its deadline, so it times out. The fast task prints two steps and finishes on its third resume, inside its deadline.
Note
no real clock is used here, so the same run always gives the same result.
Try it Yourself
Edit the code, then press Run.
Running is simulated
Exercise
A task has deadline tick 2 and needs 4 steps, one step per tick. What happens?