Closing Channels in Lua

-- In this example we'll use a `jobs` table to communicate work to be done
-- from the main thread to a worker coroutine. When we have no more jobs for
-- the worker we'll set a flag to indicate completion.

local jobs = {}
local done = false

-- Here's the worker coroutine. It repeatedly receives from `jobs` table.
-- We use a flag `done` to notify when we've worked all our jobs.
local worker = coroutine.create(function()
    while true do
        if #jobs > 0 then
            local j = table.remove(jobs, 1)
            print("received job", j)
        elseif done then
            print("received all jobs")
            return
        else
            coroutine.yield()
        end
    end
end)

-- This sends 3 jobs to the worker by inserting into the `jobs` table,
-- then sets the `done` flag.
for j = 1, 3 do
    table.insert(jobs, j)
    print("sent job", j)
end
done = true
print("sent all jobs")

-- We resume the worker coroutine until it's finished
while coroutine.status(worker) ~= "dead" do
    coroutine.resume(worker)
end

-- After all jobs are processed, trying to get more jobs will return nil
print("received more jobs:", #jobs > 0)

In this Lua version, we’ve adapted the concept of channels to use a table (jobs) and a flag (done) for communication between the main thread and a coroutine (which replaces the goroutine in the original example).

The worker is implemented as a coroutine that continuously checks for jobs in the jobs table. It yields when there are no jobs available, allowing the main thread to add more jobs.

The main thread sends jobs by inserting them into the jobs table, and signals completion by setting the done flag to true.

We use a loop to repeatedly resume the worker coroutine until it’s finished (i.e., its status becomes “dead”).

Finally, we check if there are any more jobs left in the jobs table, which will be empty if all jobs have been processed.

This example demonstrates how to implement a simple producer-consumer pattern in Lua using coroutines, tables, and flags for synchronization.

To run this program, save it as closing_channels.lua and use the Lua interpreter:

$ lua closing_channels.lua
sent job 1
received job 1
sent job 2
received job 2
sent job 3
received job 3
sent all jobs
received all jobs
received more jobs: false

This example showcases Lua’s coroutines as a way to achieve concurrent-like behavior, albeit not true parallelism as in the original example.