On Sat, May 18, 2013 at 10:33 PM, Antoine Pitrou <solip...@pitrou.net> wrote: > On Sat, 18 May 2013 16:22:55 +0200 > Armin Rigo <ar...@tunes.org> wrote: >> Hi Antoine, >> >> On Sat, May 18, 2013 at 3:45 PM, Antoine Pitrou <solip...@pitrou.net> wrote: >> >> How is this done? I don't see a clear way to determine it by looking >> >> only at the objects in the CI, given that arbitrary modifications of >> >> the object graph may have occurred. >> > >> > The same way a generation is traversed, but restricted to the CI. >> > >> > First the gc_refs field of each CI object is initialized to its >> > ob_refcnt (again). >> > >> > Then, tp_traverse is called on each CI object, and each visited >> > CI object has its gc_refs decremented. This substracts CI-internal >> > references from the gc_refs fields. >> > >> > At the end of the traversal, if all CI objects have their gc_refs equal >> > to 0, then the CI has no external reference to it and can be cleared. >> > If at least one CI object has non-zero gc_refs, the CI cannot be >> > cleared. >> >> Ok, indeed. Then you really should call finalizers only once: in case >> one of the finalizers in a cycle did a trivial change like I >> described, the algorithm above will conservatively assume the cycle >> should be kept alive. At the next GC collection we must not call the >> finalizer again, because it's likely to just do a similar trivial >> change. > > Well, the finalizer will only be called if the resurrected object is > dereferenced again; otherwise the object won't be considered by the GC. > So, this will only happen if someone keeps trying to destroy a > resurrected object. > > Calling finalizers only once is fine with me, but it would be a change > in behaviour; I don't know if it may break existing code. > > (for example, say someone is using __del__ to manage a freelist) > > Regards > > Antoine.
PyPy already ever calls finalizers once. If you resurrect an object, it'll be alive, but it's finalizer will not be called again. We discussed a few changes a while ago and we decided (I think even debated on python-dev) than even such behavior is correct: * you have a reference cycle A <-> B, C references A. C references itself. * you collect the stuff. We do topological order, so C finalizer is called first (they're only undefined inside a cycle) * then A and B finalizers are called in undefined order, even if C finalizer would resurrect C. * no more finalizers for those objects are called I'm not sure if it's cool for CPython or not to do such changes Cheers, fijal _______________________________________________ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com