Timeouts in Lua

In Lua, we can implement timeouts using the os.time() function and coroutines. Here’s how we can translate the Go example:

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

local function async(f)
    return coroutine.create(f)
end

local function await(co)
    return coroutine.resume(co)
end

local function main()
    -- For our example, suppose we're executing an external
    -- call that returns its result after 2s. We'll use a coroutine
    -- to simulate this behavior.
    local c1 = async(function()
        sleep(2)
        return "result 1"
    end)

    -- Here's the implementation of a timeout.
    -- We'll use os.time() to check if we've exceeded our timeout.
    local start = os.time()
    local timeout = 1
    local result

    while os.time() - start < timeout do
        local status, res = await(c1)
        if status then
            result = res
            break
        end
    end

    if result then
        print(result)
    else
        print("timeout 1")
    end

    -- If we allow a longer timeout of 3s, then we'll get the result.
    local c2 = async(function()
        sleep(2)
        return "result 2"
    end)

    start = os.time()
    timeout = 3
    result = nil

    while os.time() - start < timeout do
        local status, res = await(c2)
        if status then
            result = res
            break
        end
    end

    if result then
        print(result)
    else
        print("timeout 2")
    end
end

main()

Running this program shows the first operation timing out and the second succeeding:

$ lua timeouts.lua
timeout 1
result 2

In this Lua implementation:

  1. We define a sleep function to simulate waiting for a specified number of seconds.

  2. We use coroutines to simulate asynchronous operations. The async function creates a coroutine, and await resumes it.

  3. In the main function, we create two coroutines that simulate long-running operations.

  4. For each operation, we implement a timeout using a while loop that checks if we’ve exceeded our timeout period.

  5. If we get a result before the timeout, we print it. Otherwise, we print a timeout message.

This implementation mimics the behavior of the original example, showing how we can handle timeouts in Lua. Note that Lua doesn’t have built-in concurrency primitives like channels, so we use coroutines to simulate concurrent behavior.