Building a Simple Event Loop
Implement a coroutine scheduler with a run queue and resume loop.
Building a Simple Event Loop is a free Lua Academy lesson on CoddyKit — lesson 1 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the Lua Academy learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.
What Is an Event Loop?
An event loop runs a scheduler that resumes coroutines when their awaited events are ready. It enables multiple concurrent tasks without OS threads.
The Run Queue
Start with a queue of ready coroutines. Each tick, process all ready coroutines one by one.
local queue = {}
local function spawn(fn)
queue[#queue+1] = coroutine.create(fn)
endThe Loop Tick
Each tick pops and resumes each ready coroutine. Coroutines that yield are paused until re-added to the queue.
local function runLoop()
while #queue > 0 do
local current = queue
queue = {}
for _, co in ipairs(current) do
local ok, err = coroutine.resume(co)
if not ok then print("Error:", err) end
if coroutine.status(co) ~= "dead" then
queue[#queue+1] = co -- re-queue if still alive
end
end
end
endYielding to Pause
A coroutine yields when it needs to wait. The scheduler resumes it on the next tick.
spawn(function()
print("Task A: step 1")
coroutine.yield() -- pause
print("Task A: step 2")
end)
spawn(function()
print("Task B: only step")
end)
runLoop()Simulated Delays
Implement a sleep by tracking when a coroutine should wake up.
local timers = {}
local function sleep(seconds)
local wakeAt = os.clock() + seconds
timers[coroutine.running()] = wakeAt
coroutine.yield()
endTimer-Aware Loop
In each tick, check timers and re-queue coroutines whose wake time has passed.
local function timedLoop()
while #queue > 0 or next(timers) do
local now = os.clock()
for co, wakeAt in pairs(timers) do
if now >= wakeAt then
timers[co] = nil
queue[#queue+1] = co
end
end
-- process queue...
end
endI/O Integration
Integrate with a select/poll mechanism: yield coroutines waiting on I/O, and resume them when their file descriptor becomes ready.
Error Isolation
Wrap each coroutine resume in pcall or check the ok return value. A crashing coroutine should not bring down the whole loop.
Cooperative Scheduling
Tasks must voluntarily yield. A coroutine that runs forever without yielding will starve all others. Use debug.sethook with a step counter as a preemption guard for untrusted code.
Task Priorities
Implement multiple queues (high/normal/low priority) and drain higher-priority queues first each tick.
Real-World Alternatives
Production event loops: luv (libuv bindings), copas (socket-based), OpenResty (nginx + cosockets). Roll your own only for learning or embedded use.
Event Loop Question
Why must coroutines in a cooperative event loop yield voluntarily?
Recap: Simple Event Loop
An event loop uses a run queue of coroutines. Each tick resumes ready coroutines. Tasks yield to pause, and are re-queued when their condition is met. This enables concurrent I/O and timers in single-threaded Lua.
Frequently asked questions
Is the “Building a Simple Event Loop” lesson free?
Yes — the full text of “Building a Simple Event Loop” is free to read here on the web, and the Lua Academy course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the Lua Academy course, upgrade to CoddyKit PRO.
What will I learn in “Building a Simple Event Loop”?
Implement a coroutine scheduler with a run queue and resume loop. You practise Lua Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.
Do I need any experience to start Lua Academy?
No prior experience is required. Lua Academy on CoddyKit is structured for beginners through advanced learners; this is — lesson 1 of 4, so you can start here or from the beginning and move at your own pace.
How long does the “Building a Simple Event Loop” lesson take?
Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.
Can I write and run code in this Lua Academy lesson?
Yes. Every Lua Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.
All lessons in this course
- Building a Simple Event Loop
- Async/Await with Coroutines
- Promise-Like Patterns
- Non-Blocking I/O with luasocket