lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


That certainly explains why it's being done. I'm interested that the version
of the code that sets table entries to nil just before invoking next seems
not to have trouble.

It seems pretty useful, however, to have a way to walk through a table and
clear entries in the table either selectively or wholesale. One could do
this by building another table off to the side containing keys to clear;
e.g.:

    local clearkeys = {}

    for k, v in pairs( t ) do
        if shouldClear( k, v ) then
            table.insert( clearkeys, k )
        end
    end

    for _, k in ipairs( clearkeys ) do
        t[ k ] = nil
    end

This, however, seems like a lot of overhead. Certainly in the case of
completely clearing the table it would probably argue for just allocating a
new table and letting the GC collect the old one despite the memory
allocation traffic that creates.

If making this work would impair non-clearing iteration, could the practice
be banned for for-loops but allowed for table.foreach without causing too
much trouble? For example, table.foreach might be able to run one element
ahead on the iteration and the restriction could be imposed that only the
current element in the table is eligible for clearing. Of course, this might
not be particularly more efficient than the scheme above if it involved
allocating a closure to pass to table.foreach.

Or one could define:

    table.clear( t [ , func ] )

This iterates the table clearing entries. If func is supplied, it will be
passed the key/value pair for an entry and can return a true value to
request deletion and a false value to keep the entry. If func is not
supplied, then all entries will be cleared.

Mark

on 12/2/04 7:57 AM, Roberto Ierusalimschy at roberto@inf.puc-rio.br wrote:

>> That exact code is called removekey in lgc.c in Lua 5.0.2.
> 
> Yes, but in 5.0 it was called only to remove dead keys from weak
> tables. Now it is called to remove all unused keys from a table.
> 
> The problem is created by incremental collection (as expected).
> Assume the following sequence of events:
> 
> - a[x] = nil
> - a is traversed; because x has a nil value, it is not marked.
> - a[x] = non-nil; because x is not a new key, there is no write barrier.
> - x = nil; now the only reference to "x" is as a key, which was not
> marked;
> - x is collected, leaving a dangling reference in table a.
> 
> So, either x must be cleared from table a (so that a[x] = non-nil
> triggers a write barrier) or the write barrier must be more complex
> (bad for performance); or we find something better (try to put the
> work on the `next' function?).
> 
> -- Roberto