Possible Duplicate:
Why doesn't the weakref work on this bound method?
A bit of context:
I was trying to implement an Listener (or Observer, same thing) pattern: An EventManager keeps a list of all the Listeners handlers interested in an Event. For example, a Listener object would have a onEndOfTheWorldEvent
method which would be called by the EventManager each time an instance of the event class EndOfTheWorldEvent is posted. Easy.
Except that I wanted to weak reference the handlers because I don't want the EventManager to keep my handlers (bound methods) alive when the Listener was not needed anymore.
So I thought "Let's throw all the handlers in a WeakSet". I couldn't get it to work.
I dump here the code (or what's left of it when I reduce it to the minimum, here there's only one type of event and only one type of handler).
#! /usr/bin/python
"""
"""
import sys
import weakref
class Listener(object):
def handler(self, event):
print event
class EventManager(object):
def __init__(self):
self.handlers = weakref.WeakSet()
def register(self, listener):
print "Registering..."
self.handlers.add(listener.handler)
CountRefs(listener.handler)
print "Number of handlers registered:", len(self.handlers)
print "Registered."
def CountRefs(what):
print "Hard count:", sys.getrefcount(what)
print "Weak count:", weakref.getweakrefcount(what)
listener = Listener()
em = EventManager()
CountRefs(listener.handler)
em.register(listener)
CountRefs(listener.handler)
result:
Hard count: 3
Weak count: 0
Registering...
Hard count: 3
Weak count: 0
Number of handlers registered: 0
Registered.
Hard count: 3
Weak count: 0
It just looks like there's never any weak reference, and the set remains empty.
To make it even simpler:
>>> class C(object):
>>> def blah(self):
>>> print "blah"
>>>
>>> c = C()
>>> w = weakref.ref(c.blah)
>>> print w
<weakref at 0x11e59f0; dead>
Can't I create weakrefs to methods at all ? If not, why not ?
So I guess a workaround would be to replace the WeakSet with a WeakKeyDictionary: key is the listener itself, and value the handler. Indeed I can weakref my Listeners. But it makes the data structure a bit more complicated, and when comes the time to broadcast the events to everybody, there's one more level in that structure to go through.
What do you think ?
Use long weak references only when necessary as the state of the object is unpredictable after finalization. Avoid using weak references to small objects because the pointer itself may be as large or larger. Avoid using weak references as an automatic solution to memory management problems.
When a weak reference A is created to an object B, there would be an entry in the hashtable modified or created, whose key would be the pointer to B. "Dirty" - to store a special hash-value with each object, which would be zeroed when the object is destroyed.
A weak reference is just a pointer to an object that doesn't protect the object from being deallocated by ARC. While strong references increase the retain count of an object by 1, weak references do not. In addition, weak references zero out the pointer to your object when it successfully deallocates.
Weak reference objects, which do not prevent their referents from being made finalizable, finalized, and then reclaimed. Weak references are most often used to implement canonicalizing mappings. Suppose that the garbage collector determines at a certain point in time that an object is weakly reachable.
Let's say you want weakrefs on a method "meth".
You can get weakrefs on it like this
weak_obj = weakref.ref(meth.im_self)
weak_func = weakref.ref(meth.im_func)
So, you can deref it like that
obj = weak_obj()
func = weak_func()
and get "meth" back with
meth = getattr(obj, func.__name__)
listener.handler
gives you a new bound reference to the function each time. So it gets garbage collected almost immediately.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With