Search code examples
lua

What happens to abandoned coroutine in Lua


I wonder what happens with the coroutine in this example:

function powersOfTwo(i)
    coroutine.yield(i)
    powersOfTwo(2*i)
end

function iterator()
    return coroutine.wrap(function () powersOfTwo(1) end)
end

for power in iterator() do
    print(power)
    if power > 1000 then break end
end

The coroutine does not finish its code. Is it garbage collected?


Solution

  • The coroutine does not finish its code. Is it garbage collected?

    Yes, it is garbage-collected as there are no references to the coroutine left after the loop has finished execution. The fact that this involves a coroutine doesn't make a difference; if iterator() returned a closure, it would be garbage-collected all the same.

    You can verify this by using collectgarbage:

    -- Declare functions, which won't be garbage-collected as they're in the global table
    function collectgarbage_full()
        for _ = 1, 10 do -- Run multiple cycles to ensure that all garbage is collected even if the generational GC of Lua 5.2 or later is used
            collectgarbage"collect"
        end
    end
    function powersOfTwo(i)
        coroutine.yield(i)
        powersOfTwo(2*i)
    end
    function iterator()
        return coroutine.wrap(function() powersOfTwo(1) end)
    end
    -- Count non-garbage used memory
    collectgarbage_full()
    local used = collectgarbage"count"
    -- Now use the iterator, creating a garbage coroutine
    for power in iterator() do
        print(power)
        if power > 1000 then break end
    end
    -- Collect garbage, compare used memory against used memory before the garbage coroutine
    collectgarbage_full()
    if used < collectgarbage"count" then
        error"Garbage coroutine was not collected!"
    end
    print"Coroutine was garbage-collected."
    

    You should see the following output:

    1
    2
    4
    8
    16
    32
    64
    128
    256
    512
    1024
    Coroutine was garbage-collected.