[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