Channel Synchronization in Lua

Channel synchronization in Lua can be achieved using coroutines and a custom implementation of channels. Here’s an example of using a blocking receive to wait for a coroutine to finish:

local function sleep(n)
    local t0 = os.clock()
    while os.clock() - t0 <= n do end
end

local function worker(done)
    io.write("working...")
    sleep(1)  -- Simulate work
    print("done")
    done(true)  -- Send a value to notify that we're done
end

local function make_channel()
    local value
    local hasValue = false
    return {
        send = function(v)
            value = v
            hasValue = true
        end,
        receive = function()
            while not hasValue do
                coroutine.yield()
            end
            hasValue = false
            return value
        end
    }
end

local function main()
    local done = make_channel()
    
    -- Start a worker coroutine, giving it the channel to notify on
    coroutine.wrap(function() worker(done.send) end)()
    
    -- Block until we receive a notification from the worker on the channel
    done.receive()
end

main()

This Lua code demonstrates channel synchronization using coroutines. Here’s how it works:

  1. We define a sleep function to simulate work, as Lua doesn’t have a built-in sleep function.

  2. The worker function simulates some work and then notifies when it’s done using the done function passed to it.

  3. We implement a basic channel mechanism using the make_channel function. This returns an object with send and receive methods.

  4. In the main function, we create a channel and start the worker in a new coroutine.

  5. We then wait for the worker to finish by calling done.receive(), which blocks until a value is sent on the channel.

To run this program:

$ lua channel_synchronization.lua
working...done

If you removed the done.receive() line from this program, the program would exit before the worker even started, as the main thread wouldn’t wait for the coroutine to complete.

Note that Lua doesn’t have built-in concurrency primitives like goroutines or channels. This example uses coroutines and a custom channel implementation to achieve similar behavior. In a real-world scenario, you might want to use a Lua concurrency library for more robust implementations.