From: David McCusker Subject: strong vs. weak refs (was Fwd: Why we leak: a prelude) Date: 26 Apr 1999 00:00:00 GMT Message-ID: <3724E6AD.5F7482C5@netscape.com> Content-Transfer-Encoding: 7bit References: <3724BA9A.9C47AB18@netscape.com> To: pinkerton@netscape.com Content-Type: text/plain; charset=us-ascii Organization: Ontology Mechanics Guild Mime-Version: 1.0 Reply-To: davidmc@netscape.com Newsgroups: netscape.public.mozilla.general,netscape.public.mozilla.xpcom,netscape.public.mozilla.layout scc@netscape.com (Scott Collins) wrote: > Here is a starter set of simple and obvious guidelines. Our code > violates these guidelines everywhere. > > (1a1) Parents own their children; > > (1a2) Children do _not_ own their parents; > > (1a3) You don't need to own an object whose lifetime is guaranteed > to be longer than yours; > > (1a4) You don't own an object because _you_ need _it_; you own it > because _it_ needs _you_ > > (1a5) You don't want to own an object that (even transitively) owns > you As a tool for implementing a robust ownership model, simple refcounting is not sufficient in real (i.e. complex) applications unless one can distinguish between strong and weak references. I can explain these rather well in terms of the 1a* bullets in Scott Collins' message. A weak ref is for memory management purposes, so a pointer to an object does not go away and leave a dangling pointer. But a weak ref does not force an object to stay open for business and usable. A strong ref is a weak ref plus a use ref, so the weak ref keeps an object from being collected, and the use ref keeps the object from being closed. The idea of 'use' is a generalization of the idea of owership, where counting owners permits more than one owner to keep an object open. To support weak and strong refs, one possible implementation model keeps a use count seperate from a ref count, where uses must never become any fewer than refs. When strong refs are released, uses are always dropped first before refs, so an object will always finish closing with a nonzero ref count. This prevents the possibility of self-deletion while closing. Strong ref graphs must be acyclic, so that no cycles exist that stop objects from closing when owners are finished using them. Closing an object causes it to release ALL references to other objects, both weak and strong. But closing an object does not cause it to be deleted. Weak ref graphs are allowed to be cyclic, and the cycles do not prevent garbage collection in practice because the closing of objects when strong refs hit zero will cause all refs including weak ones to be released, and this causes weak graphs to come undone at exactly the rate needed when owners of objects finish using them. Parents typically own children with a strong ref. When a child must know about it's parent (or any ancestor at all), such refs must be weak. A weak ref is typically a backpointer to some driving object, and they often create reference cycles, which is okay as long as the strong refs alone create no cycles, since weak refs never stop objects from closing. Currently all the refcounting in our code amounts to strong references alone, and this is a problem for more than one reason. First, any cycles will create serious leaks. Second, it is hard to remove all cycles from the strong ref graph, because complex apps usually need some backpointers if only for performance reasons. Third, releasing refs from destructors causes a complex dependency between closing and collection. I expect our code to keep having leaks until we start using weak refs in addition to strong refs. And unless we drop the use counts before ref counts, we will have self-deletion problems when closing objects. The most annoying thing about the weak and strong ref discipline is that one must create a polymorphic close method that obviates the need for C++ destructors, since by the time an object is destroyed it had better be already closed, in which case there's nothing to do in the destructor. So a destructor can only useful assert that close has already happened. The weak and strong ref discipline is not just theory, because I've used it before, and it is currently being used by Mork in the mail/news tree. David McCusker, making a little difference (iota inside(tm)) Values have meaning only against the context of a set of relationships.