On Thu, May 22, 2014 at 12:36 PM, Eric Wing <ewmailing@gmail.com> wrote:
In this example:
- I create objectZ, objectA, and objectB (in that order).
- objectA keeps a strong reference to objectB and objectZ.
- I remove references to objectB and objectZ, proving objectA is
keeping them alive.
- I remove my reference to objectA and watch what garbage collection does.
I expect that objectA is "marked for finalization" first because it is
keeping objectB and objectZ alive.
Then objectB and objectZ may be "marked for finalization" (no order on
these is expected).
So "in the reverse order they were marked for finalization", I expect
the finalization order to be:
1) objectZ or objectB
2) objectB or objectZ
3) objectA
Your behavior is derived from expectations of a reference-counted
garbage collector. Lua doesn't refcount. It's mark-and-sweep -- as a
high-level overview, it maintains a list of all objects, and a list of
root objects (mostly the top-level _ENV and the registry). When it
does a sweep, it starts from the root objects and marks every object
that it can reach as accessible. Then it sweeps over the list of all
objects and flags every object that isn't marked as accessible for
finalization. Then it runs finalizers on the objects thus marked, in
reverse of the order that they were marked. On the next sweep, if the
object is marked as both "finalized" and "inaccessible" it's deleted.
(If it's marked as "finalized" but NOT marked as "inaccessible" it's
been resurrected. It'll never have the finalizer run again.)