[pypy-commit] pypy gc-del: Weakrefs, some small simplifications.

arigo noreply at buildbot.pypy.org
Fri Apr 26 10:43:24 CEST 2013


Author: Armin Rigo <arigo at tunes.org>
Branch: gc-del
Changeset: r63629:8cf66f2f61cd
Date: 2013-04-26 10:29 +0200
http://bitbucket.org/pypy/pypy/changeset/8cf66f2f61cd/

Log:	Weakrefs, some small simplifications.

diff --git a/pypy/interpreter/baseobjspace.py b/pypy/interpreter/baseobjspace.py
--- a/pypy/interpreter/baseobjspace.py
+++ b/pypy/interpreter/baseobjspace.py
@@ -165,7 +165,7 @@
         self.invoke_finalizer()
 
     def invoke_finalizer(self):
-        raise NotImplementedError
+        raise NotImplementedError    # must be overridden
 
     def finalizer_perform(self, space, descrname, callback, *args):
         """For use in invoke_finalizer().  First check if we're called
diff --git a/pypy/module/_weakref/interp__weakref.py b/pypy/module/_weakref/interp__weakref.py
--- a/pypy/module/_weakref/interp__weakref.py
+++ b/pypy/module/_weakref/interp__weakref.py
@@ -3,7 +3,7 @@
 from pypy.interpreter.error import OperationError
 from pypy.interpreter.gateway import interp2app, ObjSpace
 from pypy.interpreter.typedef import TypeDef
-from rpython.rlib import jit
+from rpython.rlib import rgc, jit
 from rpython.rlib.rshrinklist import AbstractShrinkList
 from rpython.rlib.objectmodel import specialize
 import weakref
@@ -14,7 +14,7 @@
         return wref() is not None
 
 
-class WeakrefLifeline(W_Root):
+class WeakrefLifeline(object):
     cached_weakref  = None
     cached_proxy    = None
     other_refs_weak = None
@@ -97,37 +97,12 @@
                     return w_ref
         return space.w_None
 
-
-class WeakrefLifelineWithCallbacks(WeakrefLifeline):
-
-    def __init__(self, space, oldlifeline=None):
-        self.space = space
-        if oldlifeline is not None:
-            self.cached_weakref  = oldlifeline.cached_weakref
-            self.cached_proxy    = oldlifeline.cached_proxy
-            self.other_refs_weak = oldlifeline.other_refs_weak
-
-    def __del__(self):
-        """This runs when the interp-level object goes away, and allows
-        its lifeline to go away.  The purpose of this is to activate the
-        callbacks even if there is no __del__ method on the interp-level
-        W_Root subclass implementing the object.
-        """
-        if self.other_refs_weak is None:
-            return
-        items = self.other_refs_weak.items()
-        for i in range(len(items)-1, -1, -1):
-            w_ref = items[i]()
-            if w_ref is not None and w_ref.w_callable is not None:
-                w_ref.enqueue_for_destruction(self.space,
-                                              W_WeakrefBase.activate_callback,
-                                              'weakref callback of ')
-
     def make_weakref_with_callback(self, w_subtype, w_obj, w_callable):
         space = self.space
         w_ref = space.allocate_instance(W_Weakref, w_subtype)
         W_Weakref.__init__(w_ref, space, w_obj, w_callable)
         self.append_wref_to(w_ref)
+        rgc.register_finalizer(self.finalizer)
         return w_ref
 
     def make_proxy_with_callback(self, w_obj, w_callable):
@@ -137,8 +112,24 @@
         else:
             w_proxy = W_Proxy(space, w_obj, w_callable)
         self.append_wref_to(w_proxy)
+        rgc.register_finalizer(self.finalizer)
         return w_proxy
 
+    def finalizer(self):
+        """This runs when the interp-level object goes away, and allows
+        its lifeline to go away.  The purpose of this is to activate the
+        callbacks even if there is no __del__ method on the interp-level
+        W_Root subclass implementing the object.
+        """
+        assert self.other_refs_weak is not None
+        items = self.other_refs_weak.items()
+        for i in range(len(items)-1, -1, -1):
+            w_ref = items[i]()
+            if w_ref is not None and w_ref.w_callable is not None:
+                w_ref.finalizer_perform(self.space, 'weakref callback of ',
+                                        self.space.call_function,
+                                        w_ref.w_callable, w_ref)
+
 # ____________________________________________________________
 
 class Dummy:
@@ -166,10 +157,6 @@
     def clear(self):
         self.w_obj_weak = dead_ref
 
-    def activate_callback(w_self):
-        assert isinstance(w_self, W_WeakrefBase)
-        w_self.space.call_function(w_self.w_callable, w_self)
-
     def descr__repr__(self, space):
         w_obj = self.dereference()
         if w_obj is None:
@@ -232,21 +219,13 @@
         w_obj.setweakref(space, lifeline)
     return lifeline
 
-def getlifelinewithcallbacks(space, w_obj):
-    lifeline = w_obj.getweakref()
-    if not isinstance(lifeline, WeakrefLifelineWithCallbacks):  # or None
-        oldlifeline = lifeline
-        lifeline = WeakrefLifelineWithCallbacks(space, oldlifeline)
-        w_obj.setweakref(space, lifeline)
-    return lifeline
-
 @jit.dont_look_inside
 def get_or_make_weakref(space, w_subtype, w_obj):
     return getlifeline(space, w_obj).get_or_make_weakref(w_subtype, w_obj)
 
 @jit.dont_look_inside
 def make_weakref_with_callback(space, w_subtype, w_obj, w_callable):
-    lifeline = getlifelinewithcallbacks(space, w_obj)
+    lifeline = getlifeline(space, w_obj)
     return lifeline.make_weakref_with_callback(w_subtype, w_obj, w_callable)
 
 def descr__new__weakref(space, w_subtype, w_obj, w_callable=None,
@@ -319,7 +298,7 @@
 
 @jit.dont_look_inside
 def make_proxy_with_callback(space, w_obj, w_callable):
-    lifeline = getlifelinewithcallbacks(space, w_obj)
+    lifeline = getlifeline(space, w_obj)
     return lifeline.make_proxy_with_callback(w_obj, w_callable)
 
 def proxy(space, w_obj, w_callable=None):
diff --git a/pypy/module/_weakref/test/test_weakref.py b/pypy/module/_weakref/test/test_weakref.py
--- a/pypy/module/_weakref/test/test_weakref.py
+++ b/pypy/module/_weakref/test/test_weakref.py
@@ -1,6 +1,9 @@
 class AppTestWeakref(object):
     spaceconfig = dict(usemodules=('_weakref',))
-                    
+
+    def setup_class(cls):
+        cls.w_appdirect = cls.space.wrap(cls.runappdirect)
+
     def test_simple(self):
         import _weakref, gc
         class A(object):
@@ -287,7 +290,11 @@
         seen_del = []
         class A(object):
             def __del__(self):
-                seen_del.append(id(self))
+                if self.appdirect:
+                    my_id = id(self)
+                else:
+                    my_id = aid    # might be different when non-translated
+                seen_del.append(my_id)
                 seen_del.append(w1() is None)
                 seen_del.append(w2() is None)
         seen_callback = []


More information about the pypy-commit mailing list