lua-users home
lua-l archive

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


On Tue, May 20, 2014 at 06:01:03PM -0700, Tim Hill wrote:
> 
> On May 20, 2014, at 5:15 PM, Eric Wing <ewmailing@gmail.com> wrote:
> 
> > I am trying to create a simple strong reference (Object A holds a
> > reference to Object B) such that:
> > 1) Object A keeps Object B alive (if all other references are disposed)
> > 2) B outlives A
> > 
> > I'm seeing #1, but #2 is not working.
> > 
> > I am using userdata and using set/getuservalue in Lua 5.2/5.3w2 and
> > basically putting objectB in objectA's user value table. (My specific
> > implementation has Object A keep an array of objects it keeps strong
> > references to.)
> 
> You cannot make assumptions about the order of GCing of unreferenced
> objects. Once object A is unreachable, then if the only references to B
> are via A (and hence B is also unreachable), both are GC candidates and
> can be collected in any order.
> 
> If you really need cleanup to occur in a defined order you will need to
> either release the reference to B first or make the __gc() metamethods
> co-ordinate the ordering of cleanup.

Lua will call finalizers in the reverse order of when they were marked for
finalization. That is, when they had their __gc field initialized. In
practice this usually means that objects are finalized in reverse order of
creation.

I've never depended on this behavior, but it worked against me once. In my
cqueues event library I implemented a fast condition variable (i.e. cv:wait
and cv:signal), and in the __gc metamethod added an assertion to check that
no threads are waiting on the condition variable. I reasoned [poorly] that
any thread waiting on the CV must hold a reference to it, unless there was a
bug.

Well, when the Lua VM is closed, it collects _everything_ in the same cycle.
And because CVs are often younger than the threads that wait on them, the
CVs were being collected before the threads, triggering the assertion. Oops.