[pypy-commit] pypy cffi-new-allocator: The in-line mode, internally _cffi_backend.newp_allocator()

arigo noreply at buildbot.pypy.org
Mon Jul 6 10:41:07 CEST 2015


Author: Armin Rigo <arigo at tunes.org>
Branch: cffi-new-allocator
Changeset: r78448:30a33ea339da
Date: 2015-07-06 10:41 +0200
http://bitbucket.org/pypy/pypy/changeset/30a33ea339da/

Log:	The in-line mode, internally _cffi_backend.newp_allocator()

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
@@ -25,6 +25,7 @@
         'new_function_type': 'newtype.new_function_type',
 
         'newp': 'func.newp',
+        'newp_allocator': 'func.newp_allocator',
         'cast': 'func.cast',
         'callback': 'func.callback',
         'alignof': 'func.alignof',
diff --git a/pypy/module/_cffi_backend/allocator.py b/pypy/module/_cffi_backend/allocator.py
--- a/pypy/module/_cffi_backend/allocator.py
+++ b/pypy/module/_cffi_backend/allocator.py
@@ -10,9 +10,7 @@
     _immutable_ = True
 
     def __init__(self, ffi, w_alloc, w_free, should_clear_after_alloc):
-        self.ffi = ffi
-        if w_alloc is not None and ffi.space.is_none(w_alloc): w_alloc = None
-        if w_free  is not None and ffi.space.is_none(w_free):  w_free = None
+        self.ffi = ffi    # may be None
         self.w_alloc = w_alloc
         self.w_free = w_free
         self.should_clear_after_alloc = should_clear_after_alloc
@@ -75,5 +73,16 @@
 W_Allocator.typedef.acceptable_as_base_class = False
 
 
+def new_allocator(space, ffi, w_alloc, w_free, should_clear_after_alloc):
+    if space.is_none(w_alloc):
+        w_alloc = None
+    if space.is_none(w_free):
+        w_free = None
+    if w_alloc is None and w_free is not None:
+        raise oefmt(space.w_TypeError, "cannot pass 'free' without 'alloc'")
+    alloc = W_Allocator(ffi, w_alloc, w_free, bool(should_clear_after_alloc))
+    return space.wrap(alloc)
+
+
 default_allocator = W_Allocator(None, None, None, should_clear_after_alloc=True)
 nonzero_allocator = W_Allocator(None, None, None,should_clear_after_alloc=False)
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
@@ -11,10 +11,9 @@
 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 cffi_opcode
+from pypy.module._cffi_backend import cffi_opcode, allocator
 from pypy.module._cffi_backend.ctypeobj import W_CType
 from pypy.module._cffi_backend.cdataobj import W_CData
-from pypy.module._cffi_backend.allocator import W_Allocator, default_allocator
 
 
 ACCEPT_STRING   = 1
@@ -419,7 +418,7 @@
 pointer to the memory somewhere else, e.g. into another structure."""
         #
         w_ctype = self.ffi_type(w_arg, ACCEPT_STRING | ACCEPT_CTYPE)
-        return w_ctype.newp(w_init, default_allocator)
+        return w_ctype.newp(w_init, allocator.default_allocator)
 
 
     @unwrap_spec(w_alloc=WrappedDefault(None),
@@ -442,11 +441,8 @@
 CFFI will clear it.
         """
         #
-        if self.space.is_none(w_alloc) and not self.space.is_none(w_free):
-            raise oefmt(self.w_TypeError, "cannot give free without alloc")
-        alloc = W_Allocator(self, w_alloc, w_free,
-                            bool(should_clear_after_alloc))
-        return self.space.wrap(alloc)
+        return allocator.new_allocator(self.space, self, w_alloc, w_free,
+                                       should_clear_after_alloc)
 
 
     def descr_new_handle(self, w_arg):
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
@@ -1,21 +1,20 @@
 from pypy.interpreter.error import OperationError, oefmt
 from pypy.interpreter.gateway import unwrap_spec, WrappedDefault
-from pypy.module._cffi_backend import ctypeobj, cdataobj
-from pypy.module._cffi_backend.allocator import W_Allocator, default_allocator
+from pypy.module._cffi_backend import ctypeobj, cdataobj, allocator
 
 
 # ____________________________________________________________
 
 @unwrap_spec(w_ctype=ctypeobj.W_CType, w_init=WrappedDefault(None))
 def newp(space, w_ctype, w_init):
-    return w_ctype.newp(w_init, default_allocator)
+    return w_ctype.newp(w_init, allocator.default_allocator)
 
 # ____________________________________________________________
 
 @unwrap_spec(should_clear_after_alloc=int)
-def new_allocator(space, should_clear_after_alloc):
-    alloc = W_Allocator(None, bool(should_clear_after_alloc))
-    return space.wrap(alloc)
+def newp_allocator(space, w_alloc, w_free, should_clear_after_alloc):
+    return allocator.new_allocator(space, None, w_alloc, w_free,
+                                   should_clear_after_alloc)
 
 # ____________________________________________________________
 
diff --git a/pypy/module/_cffi_backend/test/_backend_test_c.py b/pypy/module/_cffi_backend/test/_backend_test_c.py
--- a/pypy/module/_cffi_backend/test/_backend_test_c.py
+++ b/pypy/module/_cffi_backend/test/_backend_test_c.py
@@ -3402,6 +3402,37 @@
     py.test.raises(RuntimeError, "p[42]")
     py.test.raises(RuntimeError, "p[42] = -1")
 
+def test_newp_allocator():
+    BChar = new_primitive_type("char")
+    BCharPtr = new_pointer_type(BChar)
+    BCharArray = new_array_type(BCharPtr, None)
+    BInt = new_primitive_type("int")
+    BIntPtr = new_pointer_type(BInt)
+    seen = []
+    def myalloc(size):
+        seen.append(size)
+        return newp(BCharArray, "#" * size)
+    def myfree(raw):
+        seen.append(raw)
+    alloc1 = newp_allocator(None, None, True)
+    alloc2 = newp_allocator(myalloc, myfree, False)
+    p1 = alloc1(BIntPtr)
+    p2 = alloc2(BIntPtr)
+    assert typeof(p1) is BIntPtr
+    assert typeof(p2) is BIntPtr
+    assert p1[0] == 0
+    assert p2[0] == ord('#') * 0x01010101
+    assert seen == [sizeof(BInt)]
+    raw2 = cast(BCharPtr, p2)
+    del p1, p2
+    retries = 0
+    while len(seen) != 2:
+        retries += 1
+        assert retries <= 5
+        import gc; gc.collect()
+    assert seen == [sizeof(BInt), raw2]
+    assert repr(seen[1]) == "<cdata 'char[]' owning 5 bytes>"
+
 def test_version():
     # this test is here mostly for PyPy
     assert __version__ == "1.2.0"
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
@@ -317,7 +317,7 @@
         assert ffi.typeof(p2) == ffi.typeof("int[]")
         assert ffi.sizeof(p2) == 40
         assert p1[5] == 0
-        assert p2[6] != 0
+        assert p2[6] == ord('X') * 0x01010101
         del p1, p2
         retries = 0
         while len(seen) != 4:


More information about the pypy-commit mailing list