0Pricing
Lua Academy · Lesson

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)
end

The 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
end

Yielding 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()
end

Timer-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
end

I/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

  1. Building a Simple Event Loop
  2. Async/Await with Coroutines
  3. Promise-Like Patterns
  4. Non-Blocking I/O with luasocket
← Back to Lua Academy