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