On Sat, Mar 27, 2010 at 1:39 PM, Ian Ward <[email protected]> wrote: > Dominic LoBue wrote on 2010-03-05 03:56: >> Ian, >> >> I have a working implementation. By no means is it elegant, but it works. >> >> Basically instead of holding onto the specific method that is to be >> called when a signal is recieved, we instead hold onto a tuple of >> (ref(parentwithmethod), 'methodname'). When the signal is activated, >> we use getattr to get an instance of the method we want and then run >> that method. >> >> Working examples can be found here: >> http://gist.github.com/322577 >> http://gist.github.com/322576 >> > > I just want to make sure I have a good understanding of what is > happening with these references. The old way of tracking signals was a > single WeakKeyDictionary: > > signals._connections = WeakKeyDictionary({ > object_that_sends_signal : { > signal_name : [ > (callback_function, user_argument)]}}) > > And in common use the callback_function is a bound method on the object > that receives the signal. > > This receiving object may be the last thing holding a reference to the > sending object, however when the receiving object is removed the bound > method keeps it alive, in turn keeping the sending object alive and > circular references in _connections are never removed. > > The same thing happens with the current code, except _connections is now > in the sending object and nothing points to the dead objects, so I > assume they would eventually get picked up by the garbage collector. > > (please correct me if I'm wrong) >
Ian, The solution actually has nothing to do with where the bound method is being kept. Keeping the signal -> method mapping in one place is preference; I think it is a cleaner solution overall. The problem is that bound methods reference the class they are bound to, and in so doing they keep that class alive. The WeakKeyDictionary doesn't do anything (at least in my case). To give an example, say the object_that_sends_signal from your example is a property of object_that_receives_signal, and callback_function is a bound method of object_that_receives_signal. This is a circular reference: object_that_receives_signal references object_that_sends_signal, keeping the dictionary entries alive; and the bound method callback_function references object_that_receives_signal, keeping it alive as well. All the nesting that the bound_method is below prevents the weak reference from working. > One problem with your solution is that it only helps if the > callback_function is a bound method. What if it's a normal function > that happened to pull in a reference to the sending object from its > enclosing scope? > Can you give an example of what you mean? > I'll need to dig in to this a little more, I think.. > > Ian > > > > So, > > > > _______________________________________________ > Urwid mailing list > [email protected] > http://lists.excess.org/mailman/listinfo/urwid > I don't believe functions will be a problem because they don't have a im_self property. Here's an experiment to show the exact problem: class rawr(object): def blarg(self): pass a = rawr() s = a.blarg print a print s.im_self My results from an ipython session: In [15]: s.im_self Out[15]: <__main__.rawr object at 0x7f66e653b5d0> In [16]: a Out[16]: <__main__.rawr object at 0x7f66e653b5d0> -- Dominic LoBue _______________________________________________ Urwid mailing list [email protected] http://lists.excess.org/mailman/listinfo/urwid
