Author: Armin Rigo <[email protected]>
Branch: 
Changeset: r78455:7b0ceb5a2ce0
Date: 2015-07-06 12:53 +0200
http://bitbucket.org/pypy/pypy/changeset/7b0ceb5a2ce0/

Log:    Found out that ffi.gc() can be implemented without this mess of
        weakrefs.

diff --git a/pypy/module/_cffi_backend/__init__.py 
b/pypy/module/_cffi_backend/__init__.py
--- a/pypy/module/_cffi_backend/__init__.py
+++ b/pypy/module/_cffi_backend/__init__.py
@@ -37,6 +37,7 @@
         'from_handle': 'handle.from_handle',
         '_get_types': 'func._get_types',
         'from_buffer': 'func.from_buffer',
+        'gcp': 'func.gcp',
 
         'string': 'func.string',
         'buffer': 'cbuffer.buffer',
diff --git a/pypy/module/_cffi_backend/cdataobj.py 
b/pypy/module/_cffi_backend/cdataobj.py
--- a/pypy/module/_cffi_backend/cdataobj.py
+++ b/pypy/module/_cffi_backend/cdataobj.py
@@ -363,6 +363,10 @@
     def _sizeof(self):
         return self.ctype.size
 
+    def with_gc(self, w_destructor):
+        with self as ptr:
+            return W_CDataGCP(self.space, ptr, self.ctype, self, w_destructor)
+
 
 class W_CDataMem(W_CData):
     """This is the base class used for cdata objects that own and free
@@ -483,6 +487,20 @@
             self.length, self.space.type(self.w_keepalive).name)
 
 
+class W_CDataGCP(W_CData):
+    """For ffi.gc()."""
+    _attrs_ = ['w_original_cdata', 'w_destructor']
+    _immutable_fields_ = ['w_original_cdata', 'w_destructor']
+
+    def __init__(self, space, cdata, ctype, w_original_cdata, w_destructor):
+        W_CData.__init__(self, space, cdata, ctype)
+        self.w_original_cdata = w_original_cdata
+        self.w_destructor = w_destructor
+
+    def __del__(self):
+        self.space.call_function(self.w_destructor, self.w_original_cdata)
+
+
 W_CData.typedef = TypeDef(
     '_cffi_backend.CData',
     __module__ = '_cffi_backend',
diff --git a/pypy/module/_cffi_backend/cgc.py b/pypy/module/_cffi_backend/cgc.py
deleted file mode 100644
--- a/pypy/module/_cffi_backend/cgc.py
+++ /dev/null
@@ -1,29 +0,0 @@
-from rpython.rlib import jit
-
-
[email protected]_look_inside
-def gc_weakrefs_build(ffi, w_cdata, w_destructor):
-    from pypy.module._weakref import interp__weakref
-
-    space = ffi.space
-    if ffi.w_gc_wref_remove is None:
-        ffi.gc_wref_dict = {}
-        ffi.w_gc_wref_remove = space.getattr(space.wrap(ffi),
-                                             space.wrap("__gc_wref_remove"))
-
-    w_new_cdata = w_cdata.ctype.cast(w_cdata)
-    assert w_new_cdata is not w_cdata
-
-    w_ref = interp__weakref.make_weakref_with_callback(
-        space,
-        space.gettypefor(interp__weakref.W_Weakref),
-        w_new_cdata,
-        ffi.w_gc_wref_remove)
-
-    ffi.gc_wref_dict[w_ref] = (w_destructor, w_cdata)
-    return w_new_cdata
-
-
-def gc_wref_remove(ffi, w_ref):
-    (w_destructor, w_cdata) = ffi.gc_wref_dict.pop(w_ref)
-    ffi.space.call_function(w_destructor, w_cdata)
diff --git a/pypy/module/_cffi_backend/ffi_obj.py 
b/pypy/module/_cffi_backend/ffi_obj.py
--- a/pypy/module/_cffi_backend/ffi_obj.py
+++ b/pypy/module/_cffi_backend/ffi_obj.py
@@ -10,7 +10,7 @@
 from pypy.module._cffi_backend import parse_c_type, realize_c_type
 from pypy.module._cffi_backend import newtype, cerrno, ccallback, ctypearray
 from pypy.module._cffi_backend import ctypestruct, ctypeptr, handle
-from pypy.module._cffi_backend import cbuffer, func, cgc, wrapper
+from pypy.module._cffi_backend import cbuffer, func, wrapper
 from pypy.module._cffi_backend import cffi_opcode
 from pypy.module._cffi_backend.ctypeobj import W_CType
 from pypy.module._cffi_backend.cdataobj import W_CData
@@ -344,10 +344,7 @@
 Later, when this new cdata object is garbage-collected,
 'destructor(old_cdata_object)' will be called."""
         #
-        return cgc.gc_weakrefs_build(self, w_cdata, w_destructor)
-
-    def descr___gc_wref_remove(self, w_ref):
-        return cgc.gc_wref_remove(self, w_ref)
+        return w_cdata.with_gc(w_destructor)
 
 
     @unwrap_spec(replace_with=str)
@@ -586,7 +583,6 @@
                                      W_FFIObject.set_errno,
                                      doc=W_FFIObject.doc_errno,
                                      cls=W_FFIObject),
-        __gc_wref_remove = interp2app(W_FFIObject.descr___gc_wref_remove),
         addressof   = interp2app(W_FFIObject.descr_addressof),
         alignof     = interp2app(W_FFIObject.descr_alignof),
         buffer      = interp2app(W_FFIObject.descr_buffer),
diff --git a/pypy/module/_cffi_backend/func.py 
b/pypy/module/_cffi_backend/func.py
--- a/pypy/module/_cffi_backend/func.py
+++ b/pypy/module/_cffi_backend/func.py
@@ -105,3 +105,9 @@
                     "raw address on PyPy", w_x)
     #
     return cdataobj.W_CDataFromBuffer(space, _cdata, w_ctype, buf, w_x)
+
+# ____________________________________________________________
+
+@unwrap_spec(w_cdata=cdataobj.W_CData)
+def gcp(space, w_cdata, w_destructor):
+    return w_cdata.with_gc(w_destructor)
diff --git a/pypy/module/_cffi_backend/test/test_ffi_obj.py 
b/pypy/module/_cffi_backend/test/test_ffi_obj.py
--- a/pypy/module/_cffi_backend/test/test_ffi_obj.py
+++ b/pypy/module/_cffi_backend/test/test_ffi_obj.py
@@ -265,9 +265,10 @@
             assert p1[0] == 123
             seen.append(1)
         ffi.gc(p, destructor=destructor)    # instantly forgotten
+        _cffi1_backend.gcp(p, destructor=destructor)
         for i in range(5):
             if seen:
                 break
             import gc
             gc.collect()
-        assert seen == [1]
+        assert seen == [1, 1]
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to