[pypy-svn] r45485 - in pypy/dist/pypy/module/thread: . test

fijal at codespeak.net fijal at codespeak.net
Sat Aug 4 17:03:27 CEST 2007


Author: fijal
Date: Sat Aug  4 17:03:26 2007
New Revision: 45485

Modified:
   pypy/dist/pypy/module/thread/ll_thread.py
   pypy/dist/pypy/module/thread/test/test_ll_thread.py
Log:
Intermediate checkin, some support for thread.start_new_thread


Modified: pypy/dist/pypy/module/thread/ll_thread.py
==============================================================================
--- pypy/dist/pypy/module/thread/ll_thread.py	(original)
+++ pypy/dist/pypy/module/thread/ll_thread.py	Sat Aug  4 17:03:26 2007
@@ -5,8 +5,16 @@
 from pypy.rpython.extfunc import genericcallable
 from pypy.module.thread.os_thread import Bootstrapper
 from pypy.translator.tool.cbuild import cache_c_module
+from pypy.rpython.annlowlevel import cast_instance_to_base_ptr,\
+     cast_base_ptr_to_instance
 import thread, py
-
+from pypy.rpython.extregistry import ExtRegistryEntry
+from pypy.annotation import model as annmodel
+from pypy.rpython.lltypesystem.lltype import typeOf
+
+class BaseBootstrapper:
+    def bootstrap(self):
+        pass
 
 class ThreadError(Exception):
     def __init__(self, msg):
@@ -35,8 +43,9 @@
     return rffi.llexternal(name, args, result, includes=includes,
                            libraries=libraries)
 
-c_thread_start = llexternal('RPyThreadStart', [lltype.FuncType([rffi.VOIDP],
-                            rffi.VOIDP)], rffi.INT)
+CALLBACK = lltype.FuncType([rffi.VOIDP], rffi.VOIDP)
+c_thread_start = llexternal('RPyThreadStart', [CALLBACK, rffi.VOIDP], rffi.INT)
+c_thread_get_ident = llexternal('RPyThreadGetIdent', [], lltype.Void)
 
 TLOCKP = rffi.COpaque('struct RPyOpaque_ThreadLock', includes=includes)
 
@@ -62,4 +71,46 @@
     finally:
         c_thread_releaselock(lock._lock)
 
-    
+def ll_start_new_thread(l_func, arg):
+    l_arg = cast_instance_to_base_ptr(arg)
+    ident = c_thread_start(l_func, l_arg)
+    if ident == -1:
+        raise ThreadError("can't start new thread")
+    return ident
+
+class LLStartNewThread(ExtRegistryEntry):
+    _about_ = ll_start_new_thread
+
+    def compute_result_annotation(self, s_func, s_arg):
+        bookkeeper = self.bookkeeper
+        assert s_func.is_constant(), "Cannot call ll_start_new_thread with non-constant function"
+        s_result = bookkeeper.emulate_pbc_call(bookkeeper.position_key,
+                                               s_func, [s_arg])
+        assert annmodel.s_None.contains(s_result), (
+            """thread.start_new_thread(f, arg): f() should return None""")
+        return annmodel.SomeInteger()
+
+    def compute_annotation_bk(self, bookkeeper):
+        return annmodel.SomePBC([bookkeeper.getdesc(self.instance)])
+
+    def specialize_call(self, hop):
+        rtyper = hop.rtyper
+        bookkeeper = rtyper.annotator.bookkeeper
+        _callable = hop.args_s[0].const
+        args_r = [rtyper.getrepr(s_arg) for s_arg in hop.args_s]
+        ll_arg = args_r[1].lowleveltype
+        _type = lltype.FuncType([ll_arg], lltype.Void)
+        funcptr = lltype.functionptr(_type, _callable.func_name,
+                                     _callable=_callable)
+        r_result = rtyper.getrepr(hop.s_result)
+        ll_result = r_result.lowleveltype
+        args_s = [bookkeeper.immutablevalue(i) for i in [funcptr, ll_arg]]
+        obj = rtyper.getannmixlevel().delayedfunction(
+            ll_start_new_thread, args_s, annmodel.SomeInteger())
+        vlist = [hop.inputconst(typeOf(obj), obj)] + hop.inputargs(*args_r)
+        hop.exception_is_here()
+        return hop.genop('direct_call', vlist, r_result)
+
+# a simple wrapper, not to expose C functions (is this really necessary?)
+def ll_get_ident():
+    return c_thread_get_ident()

Modified: pypy/dist/pypy/module/thread/test/test_ll_thread.py
==============================================================================
--- pypy/dist/pypy/module/thread/test/test_ll_thread.py	(original)
+++ pypy/dist/pypy/module/thread/test/test_ll_thread.py	Sat Aug  4 17:03:26 2007
@@ -1,5 +1,6 @@
 
 from pypy.module.thread.ll_thread import *
+from pypy.translator.c.test.test_genc import compile
 import py
 
 def test_lock():
@@ -14,3 +15,26 @@
 def test_thread_error():
     l = ll_allocate_lock()
     py.test.raises(ThreadError, ll_release_lock, l)
+
+def test_thread_init_new():
+    """ This test works only after translation
+    """
+    py.test.skip("does not work")
+    import time
+    import thread
+
+    class X(BaseBootstrapper):
+        def __init__(self):
+            self.top = []
+
+        def bootstrap(self):
+            self.top.append(1)
+    
+    def f():
+        x = X()
+        ll_start_new_thread(X.bootstrap, x)
+        time.sleep(.3)
+        return len(x.top)
+
+    fn = compile(f, [])
+    assert fn() == 1



More information about the Pypy-commit mailing list