[pypy-commit] pypy stmgc-c8: Add unsafe_read(), for a different use case: multiple threads all

arigo noreply at buildbot.pypy.org
Wed Jun 24 09:57:34 CEST 2015


Author: Armin Rigo <arigo at tunes.org>
Branch: stmgc-c8
Changeset: r78281:4da124c51415
Date: 2015-06-24 09:53 +0200
http://bitbucket.org/pypy/pypy/changeset/4da124c51415/

Log:	Add unsafe_read(), for a different use case: multiple threads all
	reading some big shared immutable raw data

diff --git a/pypy/module/pypystm/__init__.py b/pypy/module/pypystm/__init__.py
--- a/pypy/module/pypystm/__init__.py
+++ b/pypy/module/pypystm/__init__.py
@@ -31,4 +31,5 @@
         'Empty': 'space.fromcache(queue.Cache).w_Empty',
 
         'unsafe_write': 'unsafe_op.unsafe_write',
+        'unsafe_read':  'unsafe_op.unsafe_read',
     }
diff --git a/pypy/module/pypystm/test/test_unsafe_op.py b/pypy/module/pypystm/test/test_unsafe_op.py
--- a/pypy/module/pypystm/test/test_unsafe_op.py
+++ b/pypy/module/pypystm/test/test_unsafe_op.py
@@ -13,6 +13,7 @@
         pypystm.unsafe_write(x, 1, '\xAA')
         assert x[0] == 'A'
         assert x[1] == '\xAA'
+        assert pypystm.unsafe_read(x, 1) == '\xAA'
 
     def test_unsafe_write_int32(self):
         import pypystm, _cffi_backend
@@ -23,6 +24,7 @@
         pypystm.unsafe_write(x, 1, -0x05060708)
         assert x[0] == -0x01020304
         assert x[1] == -0x05060708
+        assert pypystm.unsafe_read(x, 1) == -0x05060708
 
     def test_unsafe_write_uint64(self):
         import pypystm, _cffi_backend
@@ -33,6 +35,7 @@
         pypystm.unsafe_write(x, 1, 0xF506070855667788)
         assert x[0] == 0x0102030411223344
         assert x[1] == 0xF506070855667788
+        assert pypystm.unsafe_read(x, 1) == 0xF506070855667788
 
     def test_unsafe_write_unsupported_case(self):
         import pypystm, _cffi_backend
@@ -40,6 +43,7 @@
         BUniCharP = _cffi_backend.new_pointer_type(BUniChar)
         x = _cffi_backend.newp(_cffi_backend.new_array_type(BUniCharP, 2))
         raises(TypeError, pypystm.unsafe_write, x, 0, u'X')
+        raises(TypeError, pypystm.unsafe_read, x, 1)
 
     def test_unsafe_write_float(self):
         import pypystm, _cffi_backend
@@ -50,6 +54,7 @@
         pypystm.unsafe_write(x, 1, -42.0)
         assert x[0] == 12.25
         assert x[1] == -42.0
+        assert pypystm.unsafe_read(x, 1) == -42.0
 
     def test_unsafe_write_double(self):
         import pypystm, _cffi_backend
@@ -60,3 +65,4 @@
         pypystm.unsafe_write(x, 1, -42.0)
         assert x[0] == 12.25
         assert x[1] == -42.0
+        assert pypystm.unsafe_read(x, 1) == -42.0
diff --git a/pypy/module/pypystm/unsafe_op.py b/pypy/module/pypystm/unsafe_op.py
--- a/pypy/module/pypystm/unsafe_op.py
+++ b/pypy/module/pypystm/unsafe_op.py
@@ -3,6 +3,7 @@
 from pypy.module._cffi_backend import cdataobj, ctypeptr, ctypeprim, misc
 from rpython.rtyper.lltypesystem import lltype, rffi
 from rpython.rlib.objectmodel import specialize
+from rpython.rlib.rarithmetic import intmask
 
 
 @specialize.memo()
@@ -73,3 +74,65 @@
 
     raise oefmt(space.w_TypeError, "unsupported type in unsafe_write(): '%s'",
                 ctitem.name)
+
+# ____________________________________________________________
+
+
+def unsafe_read_raw_signed_data(w_cdata, index, size):
+    with w_cdata as target:
+        for TP, _ in misc._prim_signed_types:
+            if size == rffi.sizeof(TP):
+                TPP = get_unsafe_type_ptr(TP)
+                value = rffi.cast(TPP, target)[index]
+                return rffi.cast(lltype.Signed, value)
+    raise NotImplementedError("bad integer size")
+
+def unsafe_read_raw_unsigned_data(w_cdata, index, size):
+    with w_cdata as target:
+        for TP, _ in misc._prim_unsigned_types:
+            if size == rffi.sizeof(TP):
+                TPP = get_unsafe_type_ptr(TP)
+                value = rffi.cast(TPP, target)[index]
+                return rffi.cast(lltype.Unsigned, value)
+    raise NotImplementedError("bad integer size")
+
+def unsafe_read_raw_float_data(w_cdata, index, size):
+    with w_cdata as target:
+        for TP, _ in misc._prim_float_types:
+            if size == rffi.sizeof(TP):
+                TPP = get_unsafe_type_ptr(TP)
+                value = rffi.cast(TPP, target)[index]
+                return rffi.cast(lltype.Float, value)
+    raise NotImplementedError("bad integer size")
+
+
+ at unwrap_spec(w_cdata=cdataobj.W_CData, index=int)
+def unsafe_read(space, w_cdata, index):
+    ctype = w_cdata.ctype
+    if not isinstance(ctype, ctypeptr.W_CTypePtrOrArray):
+        raise oefmt(space.w_TypeError,
+                    "expected a cdata of type pointer or array")
+    ctitem = ctype.ctitem
+
+    if isinstance(ctitem, ctypeprim.W_CTypePrimitiveChar):
+        uintvalue = unsafe_read_raw_unsigned_data(w_cdata, index, size=1)
+        return space.wrap(chr(intmask(uintvalue)))
+
+    if isinstance(ctitem, ctypeprim.W_CTypePrimitiveSigned):
+        if ctitem.value_fits_long:
+            intvalue = unsafe_read_raw_signed_data(w_cdata, index, ctitem.size)
+            return space.wrap(intvalue)
+
+    if isinstance(ctitem, ctypeprim.W_CTypePrimitiveUnsigned):
+        if ctitem.value_fits_ulong:
+            uintvalue = unsafe_read_raw_unsigned_data(w_cdata, index,
+                                                      ctitem.size)
+            return space.wrap(uintvalue)
+
+    if isinstance(ctitem, ctypeprim.W_CTypePrimitiveFloat):
+        if not isinstance(ctitem, ctypeprim.W_CTypePrimitiveLongDouble):
+            floatvalue = unsafe_read_raw_float_data(w_cdata, index, ctitem.size)
+            return space.wrap(floatvalue)
+
+    raise oefmt(space.w_TypeError, "unsupported type in unsafe_read(): '%s'",
+                ctitem.name)


More information about the pypy-commit mailing list