On Wed, Dec 12, 2012 at 1:22 PM, Andy Seaborne <[email protected]> wrote: > On 08/12/12 00:03, Claude Warren wrote: >> >> I am looking at a case where I need to register a listener to the >> model. The default implementation then converts that to a graph >> listener, so my question applies to both. >> >> I don't have a way to detect when my class will be garbage collected >> (OK, I could use finalize() but that is not guaranteed to be called). >> My plan was to have a listener registered with the model that would >> modify my class instance as appropriate. But when my class instance >> goes out of scope I want both it and the listener to be garbage >> collected. >> >> This got me wondering if the listener implementation in model (and >> graph) shouldn't have weak references to the listening entities (e.g. >> anything registered as a listener). >> >> I suppose I can make my listening implementation weakly referred and >> clean itself up but shouldn't the base implementation of listener do >> this by default? >> >> -- Claude >> > > So there does need to be a weak reference between the listener and your > class if your class is going to be a candidate for GC. > > There is a sort-of related case where there are huge numbers of listeners > and you want them to be deregistered. The problem here is to not have a > massive list of listeners. > > The event mechanism is only supposed to be a base level piece of machinery > where other things can be built on top. > > How about a separate ModelListenerAdapter2 that keeps a weak reference to > the ModelChangedListener (and model m)? > > What I'm not sure about is whether building in the WeakReferences into the > core system is right for everyone. Plus reported experience with > WeakReference in the first place (from Jeremy). If it's general, and > stable, then fine - an indirection ModelListenerAdapter2 should also work. > > If a Weakreference goes null, the listener would deregister itself I > presume? This would clearout the underlying listener tracking (a list?) so > good for long running systems not accumulating dead listeners. >
I am strongly* against implementing listeners with weak references. 1) It changes the semantics of the listener from "notify object of event until it is deregistered" to "notify object of event until object is not referenced by anybody else". There are plenty of legal situations in which you can have an object listening for events, and having no other references keeping it from GC. An example would be a listener that calls a static method, such as a Logger. 2) Leads to lazy developers who don't deregister event listeners when they should, and instead rely on garbage collection. This can cause strange bugs where the listener is cleared quickly in a development environment, but hangs around for a long time in production and causes the listener to attempt to manipulate objects that have already been destroyed (happens a lot in GUI programs, where the listener may attempt to update a window that has been disposed already). 3) Necessitates adding a garbage collection process that clears out WeakReference objects that have been abandoned. 4) Adds an additional level of indirect, which may have a performance impact when there are high event rates Ultimately I think weak references are almost always a hack that attempts to alleviate the issue of thinking about object lifecycles, but they ultimately end up causing more problems than they solve. In spite of all this, if you still want to go down the route of weak listeners for your application, then it is pretty trivial to build them on top of the existing interface with your own wrapper object. -Stephen * pun intended
