lua-users home
lua-l archive

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


Beware, however, with respect to the weak table dependency mechanism. If it
just provides acyclic dependencies you are fine. If, however, it is used for
more general references, then I think partially weak tables can result in
uncollectable cycles. For example:

    ud1 = make_user_data();
    ud2 = make_user_data();

    wt = setmetatable( {}, { __mode="k" } );

    wt[ ud1 ] = ud2;
    wt[ ud2 ] = ud1;

    ud1 = nil;
    ud2 = nil;

Despite now being "unreachable" (other than via wt) ud1 and ud2, I don't
think ud1 and ud2 will ever be collected.

This example may seem trivial, but bear in mind that the path from ud1 to
ud2 and back to ud1 could be arbitrarily circuitous. For example, with only
one userdata, consider:

    ud = make_user_data();

    udrefs = setmetatable( {}, { __mode="k" } );

    udrefs[ ud ] = { back = ud };

    ud = nil;

We still have a cycle since marking the values in udrefs will eventually
mark ud. In real applications, the path back is probably longer and harder
to spot in the code.

The only work around I know of is the moderately ugly approach of generating
unique metatables for each userdata instance needing associated Lua data and
using the metatable to store the referenced data. This runs a bit counter to
the traditional use of metatables as essentially a form of type information.

Mark