[pypy-svn] r45560 - in pypy/dist/pypy/module/thread: . test
fijal at codespeak.net
fijal at codespeak.net
Thu Aug 9 01:18:37 CEST 2007
Author: fijal
Date: Thu Aug 9 01:18:36 2007
New Revision: 45560
Modified:
pypy/dist/pypy/module/thread/ll_thread.py
pypy/dist/pypy/module/thread/test/test_ll_thread.py
Log:
Rffi implementation of start_new_thread, quite unsafe though and a bit
of XXX around, I would really appreciate if someone take a look at it
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 Thu Aug 9 01:18:36 2007
@@ -4,9 +4,9 @@
from pypy.rpython.lltypesystem.rffi import platform
from pypy.rpython.extfunc import genericcallable
from pypy.module.thread.os_thread import Bootstrapper
+from pypy.rpython.annlowlevel import cast_instance_to_base_ptr
from pypy.translator.tool.cbuild import cache_c_module
-from pypy.rpython.annlowlevel import cast_instance_to_base_ptr,\
- cast_base_ptr_to_instance
+from pypy.rpython.lltypesystem import llmemory
import thread, py
from pypy.rpython.extregistry import ExtRegistryEntry
from pypy.annotation import model as annmodel
@@ -27,14 +27,14 @@
def __init__(self, ll_lock):
self._lock = ll_lock
-includes = ['unistd.h', 'thread.h']
+includes = ['unistd.h', 'src/thread.h']
+from pypy.tool.autopath import pypydir
+pypydir = py.path.local(pypydir)
+srcdir = pypydir.join('translator', 'c', 'src')
def setup_thread_so():
- from pypy.tool.autopath import pypydir
- pypydir = py.path.local(pypydir)
- srcdir = pypydir.join('translator', 'c', 'src')
- modname = '_thread'
files = [srcdir.join('thread.c')]
+ modname = '_thread'
cache_c_module(files, modname, include_dirs=[str(srcdir)])
return str(pypydir.join('_cache', modname)) + '.so'
libraries = [setup_thread_so()]
@@ -43,9 +43,9 @@
return rffi.llexternal(name, args, result, includes=includes,
libraries=libraries)
-CALLBACK = lltype.FuncType([rffi.VOIDP], rffi.VOIDP)
+CALLBACK = lltype.Ptr(lltype.FuncType([rffi.VOIDP], rffi.VOIDP))
c_thread_start = llexternal('RPyThreadStart', [CALLBACK, rffi.VOIDP], rffi.INT)
-c_thread_get_ident = llexternal('RPyThreadGetIdent', [], lltype.Void)
+c_thread_get_ident = llexternal('RPyThreadGetIdent', [], rffi.INT)
TLOCKP = rffi.COpaque('struct RPyOpaque_ThreadLock', includes=includes)
@@ -71,46 +71,45 @@
finally:
c_thread_releaselock(lock._lock)
+# a simple wrapper, not to expose C functions (is this really necessary?)
+def ll_get_ident():
+ return c_thread_get_ident()
+
+def start_new_thread(x, y):
+ raise NotImplementedError("Should never be invoked directly")
+
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
+ l_arg = rffi.cast(rffi.VOIDP, l_arg)
+ return c_thread_start(l_func, l_arg)
class LLStartNewThread(ExtRegistryEntry):
- _about_ = ll_start_new_thread
-
+ _about_ = 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""")
+ assert annmodel.s_None.contains(s_result)
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
+ bk = rtyper.annotator.bookkeeper
+ r_result = rtyper.getrepr(hop.s_result)
+ hop.exception_is_here()
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 = hop.args_s[0].const
+ funcptr = lltype.functionptr(CALLBACK.TO, _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]]
+ func_s = bk.immutablevalue(funcptr)
+ s_args = [func_s, hop.args_s[1]]
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()
+ ll_start_new_thread, s_args, annmodel.SomeInteger())
+ bootstrap = rtyper.getannmixlevel().delayedfunction(
+ _callable, [hop.args_s[1]], annmodel.s_None)
+ vlist = [hop.inputconst(typeOf(obj), obj),
+ hop.inputconst(typeOf(bootstrap), bootstrap),
+ #hop.inputarg(args_r[0], 0),
+ hop.inputarg(args_r[1], 1)]
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 Thu Aug 9 01:18:36 2007
@@ -1,6 +1,7 @@
from pypy.module.thread.ll_thread import *
from pypy.translator.c.test.test_genc import compile
+from pypy.rpython.lltypesystem import lltype
import py
def test_lock():
@@ -16,25 +17,28 @@
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")
+def test_start_new_thread():
import time
- import thread
-
- class X(BaseBootstrapper):
+ class Y:
+ _alloc_flavor_ = 'raw'
+
def __init__(self):
self.top = []
def bootstrap(self):
- self.top.append(1)
+ self.top.append(ll_get_ident())
def f():
- x = X()
- ll_start_new_thread(X.bootstrap, x)
- time.sleep(.3)
- return len(x.top)
+ y = Y()
+ start_new_thread(Y.bootstrap, y)
+ time.sleep(1)
+ res = len(y.top)
+ lltype.free(y.top, flavor='raw')
+ lltype.free(y, flavor='raw')
+ return res == ll_get_ident()
+ # XXX is this testable on top of llinterp at all?
fn = compile(f, [])
- assert fn() == 1
+ # XXX where does additional malloc come from???
+ assert fn(expected_extra_mallocs=1) == False
+
More information about the Pypy-commit
mailing list