[pypy-svn] r26426 - in pypy/dist/pypy/module/_weakref: . test
cfbolz at codespeak.net
cfbolz at codespeak.net
Thu Apr 27 11:35:45 CEST 2006
Author: cfbolz
Date: Thu Apr 27 11:35:44 2006
New Revision: 26426
Modified:
pypy/dist/pypy/module/_weakref/__init__.py
pypy/dist/pypy/module/_weakref/interp__weakref.py
pypy/dist/pypy/module/_weakref/test/test_weakref.py
Log:
fix some problems in weakref, add getweakrefs and getweakrefcount
Modified: pypy/dist/pypy/module/_weakref/__init__.py
==============================================================================
--- pypy/dist/pypy/module/_weakref/__init__.py (original)
+++ pypy/dist/pypy/module/_weakref/__init__.py Thu Apr 27 11:35:44 2006
@@ -4,5 +4,8 @@
appleveldefs = {
}
interpleveldefs = {
- 'ref': 'interp__weakref.W_Weakref'
+ 'ref': 'interp__weakref.W_Weakref',
+ 'getweakrefcount': 'interp__weakref.getweakrefcount',
+ 'getweakrefs': 'interp__weakref.getweakrefs',
+ 'ReferenceType': 'interp__weakref.W_Weakref',
}
Modified: pypy/dist/pypy/module/_weakref/interp__weakref.py
==============================================================================
--- pypy/dist/pypy/module/_weakref/interp__weakref.py (original)
+++ pypy/dist/pypy/module/_weakref/interp__weakref.py Thu Apr 27 11:35:44 2006
@@ -4,46 +4,92 @@
from pypy.interpreter.typedef import GetSetProperty, TypeDef
from pypy.interpreter.gateway import interp2app
from pypy.rpython.objectmodel import cast_address_to_object, cast_object_to_address
-class W_Weakref(Wrappable):
- pass
+from pypy.rpython.lltypesystem.llmemory import NULL
W_Weakrefable = W_Root
W_Weakrefable.__lifeline__ = None
class W_Weakref(Wrappable):
- def __init__(w_self, space, w_obj, w_callable):
+ def __init__(w_self, space, lifeline, index, w_obj, w_callable):
w_self.space = space
w_self.address = cast_object_to_address(w_obj)
w_self.w_callable = w_callable
+ w_self.addr_lifeline = cast_object_to_address(lifeline)
+ w_self.index = index
def descr__call__(self):
return cast_address_to_object(self.address, W_Weakrefable)
def invalidate(w_self):
- from pypy.rpython.lltypesystem.llmemory import NULL
- import os
w_self.address = NULL
+
+ def activate_callback(w_self):
+ import os
if not w_self.space.is_w(w_self.w_callable, w_self.space.w_None):
try:
w_self.space.call_function(w_self.w_callable, w_self)
except OperationError, e:
os.write(2, "XXX\n")
+ def __del__(w_self):
+ if w_self.address != NULL:
+ lifeline = cast_address_to_object(w_self.addr_lifeline,
+ WeakrefLifeline)
+ lifeline.ref_is_dead(w_self.index)
+
class WeakrefLifeline(object):
def __init__(self):
- self.refs_w = []
+ self.addr_refs = []
def __del__(self):
- for i in range(len(self.refs_w) - 1, -1, -1):
- w_ref = self.refs_w[i]
- w_ref.invalidate()
+ for i in range(len(self.addr_refs) - 1, -1, -1):
+ addr_ref = self.addr_refs[i]
+ if addr_ref != NULL:
+ w_ref = cast_address_to_object(addr_ref, W_Weakref)
+ w_ref.invalidate()
+ for i in range(len(self.addr_refs) - 1, -1, -1):
+ addr_ref = self.addr_refs[i]
+ if addr_ref != NULL:
+ w_ref = cast_address_to_object(addr_ref, W_Weakref)
+ w_ref.activate_callback()
def get_weakref(self, space, w_subtype, w_obj, w_callable):
w_ref = space.allocate_instance(W_Weakref, w_subtype)
- W_Weakref.__init__(w_ref, space, w_obj, w_callable)
- self.refs_w.append(w_ref)
+ W_Weakref.__init__(w_ref, space, self, len(self.addr_refs),
+ w_obj, w_callable)
+ self.addr_refs.append(cast_object_to_address(w_ref))
return w_ref
+ def ref_is_dead(self, index):
+ self.addr_refs[index] = NULL
+
+def getweakrefcount(space, w_obj):
+ if not isinstance(w_obj, W_Weakrefable):
+ return space.wrap(0)
+ if w_obj.__lifeline__ is None:
+ return space.wrap(0)
+ else:
+ lifeline = w_obj.__lifeline__
+ result = 0
+ for i in range(len(lifeline.addr_refs)):
+ if lifeline.addr_refs[i] != NULL:
+ result += 1
+ return space.wrap(result)
+
+def getweakrefs(space, w_obj):
+ if not isinstance(w_obj, W_Weakrefable):
+ return space.newlist()
+ if w_obj.__lifeline__ is None:
+ return space.newlist()
+ else:
+ lifeline = w_obj.__lifeline__
+ result = []
+ for i in range(len(lifeline.addr_refs)):
+ addr = lifeline.addr_refs[i]
+ if addr != NULL:
+ result.append(cast_address_to_object(addr, W_Weakref))
+ return space.newlist(result)
+
def descr__new__(space, w_subtype, w_obj, w_callable=None):
assert isinstance(w_obj, W_Weakrefable)
if w_obj.__lifeline__ is None:
Modified: pypy/dist/pypy/module/_weakref/test/test_weakref.py
==============================================================================
--- pypy/dist/pypy/module/_weakref/test/test_weakref.py (original)
+++ pypy/dist/pypy/module/_weakref/test/test_weakref.py Thu Apr 27 11:35:44 2006
@@ -10,8 +10,10 @@
class A:
pass
a = A()
+ assert _weakref.getweakrefcount(a) == 0
ref = _weakref.ref(a)
assert ref() is a
+ assert _weakref.getweakrefcount(a) == 1
del a
assert ref() is None
@@ -25,6 +27,7 @@
a2.ref = ref()
ref1 = _weakref.ref(a1, callback)
ref2 = _weakref.ref(a1)
+ assert _weakref.getweakrefcount(a1) == 2
del a1
assert ref1() is None
assert a2.ref is None
@@ -44,3 +47,33 @@
del a1
assert a2.x == 42
+ def test_dont_callback_if_weakref_dead(self):
+ import _weakref
+ class A:
+ pass
+ a1 = A()
+ a1.x = 40
+ a2 = A()
+ def callback(ref):
+ a1.x = 42
+ assert _weakref.getweakrefcount(a2) == 0
+ ref = _weakref.ref(a2, callback)
+ assert _weakref.getweakrefcount(a2) == 1
+ ref = None
+ assert _weakref.getweakrefcount(a2) == 0
+ a2 = None
+ assert a1.x == 40
+
+ def test_callback_cannot_ressurect(self):
+ import _weakref
+ class A:
+ pass
+ a = A()
+ alive = A()
+ alive.a = 1
+ def callback(ref2):
+ alive.a = ref1()
+ ref1 = _weakref.ref(a, callback)
+ ref2 = _weakref.ref(a, callback)
+ del a
+ assert alive.a is None
More information about the Pypy-commit
mailing list