[pypy-commit] pypy stmgc-c7: Start a built-in module "_stm".

arigo noreply at buildbot.pypy.org
Mon Nov 10 14:56:47 CET 2014


Author: Armin Rigo <arigo at tunes.org>
Branch: stmgc-c7
Changeset: r74426:a94a7b675578
Date: 2014-11-10 14:56 +0100
http://bitbucket.org/pypy/pypy/changeset/a94a7b675578/

Log:	Start a built-in module "_stm".

diff --git a/pypy/interpreter/executioncontext.py b/pypy/interpreter/executioncontext.py
--- a/pypy/interpreter/executioncontext.py
+++ b/pypy/interpreter/executioncontext.py
@@ -34,7 +34,7 @@
         self.w_profilefuncarg = None
         #
         if self.space.config.translation.stm:
-            from pypy.module.thread.stm import initialize_execution_context
+            from pypy.module._stm.ec import initialize_execution_context
             initialize_execution_context(self)
 
     def gettopframe(self):
diff --git a/pypy/module/_stm/__init__.py b/pypy/module/_stm/__init__.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/_stm/__init__.py
@@ -0,0 +1,11 @@
+
+# Package initialisation
+from pypy.interpreter.mixedmodule import MixedModule
+
+class Module(MixedModule):
+    appleveldefs = {
+    }
+
+    interpleveldefs = {
+        'local': 'local.STMLocal',
+    }
diff --git a/pypy/module/_stm/ec.py b/pypy/module/_stm/ec.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/_stm/ec.py
@@ -0,0 +1,29 @@
+"""
+Attach extra STM-only attributes to the ExecutionContext.
+"""
+
+from pypy.interpreter.executioncontext import ExecutionContext
+from pypy.interpreter.gateway import W_Root
+
+
+class FakeWeakKeyDictionary:
+    # Only used if we don't have weakrefs.
+    # Then thread._local instances will leak, but too bad.
+    def __init__(self):
+        self.d = {}
+    def get(self, key):
+        return self.d.get(key, None)
+    def set(self, key, value):
+        self.d[key] = value
+
+def initialize_execution_context(ec):
+    """Called from ExecutionContext.__init__()."""
+    if ec.space.config.translation.rweakref:
+        from rpython.rlib import rweakref
+        from pypy.module._stm.local import STMLocal
+        ec._thread_local_dicts = rweakref.RWeakKeyDictionary(STMLocal, W_Root)
+    else:
+        ec._thread_local_dicts = FakeWeakKeyDictionary()
+    if ec.space.config.objspace.std.withmethodcache:
+        from pypy.objspace.std.typeobject import MethodCache
+        ec._methodcache = MethodCache(ec.space)
diff --git a/pypy/module/_stm/local.py b/pypy/module/_stm/local.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/_stm/local.py
@@ -0,0 +1,75 @@
+"""
+The '_stm.local' class, used for 'thread._local' with STM.
+"""
+
+from pypy.interpreter.gateway import W_Root, interp2app
+from pypy.interpreter.typedef import TypeDef, GetSetProperty, descr_get_dict
+from rpython.rlib import jit
+from rpython.rlib.objectmodel import we_are_translated
+
+
+def _fill_untranslated(ec):
+    if not we_are_translated() and not hasattr(ec, '_thread_local_dicts'):
+        from pypy.module._stm.ec import initialize_execution_context
+        initialize_execution_context(ec)
+
+
+class STMLocal(W_Root):
+    """Thread-local data"""
+
+    @jit.dont_look_inside
+    def __init__(self, space, initargs):
+        self.space = space
+        self.initargs = initargs
+        # The app-level __init__() will be called by the general
+        # instance-creation logic.  It causes getdict() to be
+        # immediately called.  If we don't prepare and set a w_dict
+        # for the current thread, then this would in cause getdict()
+        # to call __init__() a second time.
+        ec = space.getexecutioncontext()
+        _fill_untranslated(ec)
+        w_dict = space.newdict(instance=True)
+        ec._thread_local_dicts.set(self, w_dict)
+
+    @jit.dont_look_inside
+    def create_new_dict(self, ec):
+        # create a new dict for this thread
+        space = self.space
+        w_dict = space.newdict(instance=True)
+        ec._thread_local_dicts.set(self, w_dict)
+        # call __init__
+        try:
+            w_self = space.wrap(self)
+            w_type = space.type(w_self)
+            w_init = space.getattr(w_type, space.wrap("__init__"))
+            space.call_obj_args(w_init, w_self, self.initargs)
+        except:
+            # failed, forget w_dict and propagate the exception
+            ec._thread_local_dicts.set(self, None)
+            raise
+        # ready
+        return w_dict
+
+    def getdict(self, space):
+        ec = space.getexecutioncontext()
+        _fill_untranslated(ec)
+        w_dict = ec._thread_local_dicts.get(self)
+        if w_dict is None:
+            w_dict = self.create_new_dict(ec)
+        return w_dict
+
+    def descr_local__new__(space, w_subtype, __args__):
+        local = space.allocate_instance(STMLocal, w_subtype)
+        STMLocal.__init__(local, space, __args__)
+        return space.wrap(local)
+
+    def descr_local__init__(self, space):
+        # No arguments allowed
+        pass
+
+STMLocal.typedef = TypeDef("_stm.local",
+                     __doc__ = "Thread-local data",
+                     __new__ = interp2app(STMLocal.descr_local__new__.im_func),
+                     __init__ = interp2app(STMLocal.descr_local__init__),
+                     __dict__ = GetSetProperty(descr_get_dict, cls=STMLocal),
+                     )
diff --git a/pypy/module/_stm/lock.py b/pypy/module/_stm/lock.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/_stm/lock.py
@@ -0,0 +1,21 @@
+from pypy.module.thread.error import wrap_thread_error
+
+
+class STMLock(rthread.Lock):
+    def __init__(self, space, ll_lock):
+        rthread.Lock.__init__(self, ll_lock)
+        self.space = space
+
+    def acquire(self, flag):
+        if rstm.is_atomic():
+            acquired = rthread.Lock.acquire(self, False)
+            if flag and not acquired:
+                raise wrap_thread_error(self.space,
+                    "deadlock: an atomic transaction tries to acquire "
+                    "a lock that is already acquired.  See pypy/doc/stm.rst.")
+        else:
+            acquired = rthread.Lock.acquire(self, flag)
+        return acquired
+
+def allocate_stm_lock(space):
+    return STMLock(space, rthread.allocate_ll_lock())
diff --git a/pypy/module/thread/test/__init__.py b/pypy/module/_stm/test/__init__.py
copy from pypy/module/thread/test/__init__.py
copy to pypy/module/_stm/test/__init__.py
diff --git a/pypy/module/thread/test/test_stm.py b/pypy/module/_stm/test/test_local.py
rename from pypy/module/thread/test/test_stm.py
rename to pypy/module/_stm/test/test_local.py
--- a/pypy/module/thread/test/test_stm.py
+++ b/pypy/module/_stm/test/test_local.py
@@ -2,10 +2,12 @@
 
 
 class AppTestSTMLocal(test_local.AppTestLocal):
+    spaceconfig = test_local.AppTestLocal.spaceconfig.copy()
+    spaceconfig['usemodules'] += ('_stm',)
 
     def setup_class(cls):
         test_local.AppTestLocal.setup_class.im_func(cls)
         cls.w__local = cls.space.appexec([], """():
-            import thread
-            return thread._untranslated_stmlocal
+            import _stm
+            return _stm.local
         """)
diff --git a/pypy/module/_stm/threadlocals.py b/pypy/module/_stm/threadlocals.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/_stm/threadlocals.py
@@ -0,0 +1,42 @@
+"""
+An STM-friendly subclass of OSThreadLocals.
+"""
+
+from pypy.module.thread.threadlocals import OSThreadLocals
+from rpython.rlib import rstm
+from rpython.rlib.objectmodel import invoke_around_extcall
+
+
+class STMThreadLocals(OSThreadLocals):
+    threads_running = False
+    _immutable_fields_ = ['threads_running?']
+
+    def initialize(self, space):
+        """NOT_RPYTHON: set up a mechanism to send to the C code the value
+        set by space.actionflag.setcheckinterval()."""
+        #
+        def setcheckinterval_callback():
+            self.configure_transaction_length(space)
+        #
+        assert space.actionflag.setcheckinterval_callback is None
+        space.actionflag.setcheckinterval_callback = setcheckinterval_callback
+
+    # XXX?
+    #def getallvalues(self):
+    #    raise ValueError
+
+    def setup_threads(self, space):
+        if not self.threads_running:
+            # invalidate quasi-immutable if we have threads:
+            self.threads_running = True
+        self.configure_transaction_length(space)
+        invoke_around_extcall(rstm.before_external_call,
+                              rstm.after_external_call,
+                              rstm.enter_callback_call,
+                              rstm.leave_callback_call)
+
+    def configure_transaction_length(self, space):
+        if self.threads_running:
+            interval = space.actionflag.getcheckinterval()
+            rstm.set_transaction_length(interval / 10000.0)
+
diff --git a/pypy/module/thread/__init__.py b/pypy/module/thread/__init__.py
--- a/pypy/module/thread/__init__.py
+++ b/pypy/module/thread/__init__.py
@@ -45,5 +45,3 @@
             self.extra_interpdef('_local', 'stm.STMLocal')
         else:
             self.extra_interpdef('_local', 'os_local.Local')
-            if not self.space.config.translating:
-                self.extra_interpdef('_untranslated_stmlocal', 'stm.STMLocal')
diff --git a/pypy/module/thread/stm.py b/pypy/module/thread/stm.py
--- a/pypy/module/thread/stm.py
+++ b/pypy/module/thread/stm.py
@@ -1,161 +1,8 @@
 """
-Software Transactional Memory emulation of the GIL.
-
-XXX this module may contain near-duplicated code from the non-STM variants
+Redirect some classes from pypy.module._stm.
 """
 
-from pypy.module.thread.threadlocals import OSThreadLocals
-from pypy.module.thread.error import wrap_thread_error
-from pypy.interpreter.executioncontext import ExecutionContext
-from pypy.interpreter.gateway import W_Root, interp2app
-from pypy.interpreter.typedef import TypeDef, GetSetProperty, descr_get_dict
-from rpython.rlib import rthread
-from rpython.rlib import rstm
-from rpython.rlib import jit
-from rpython.rlib.objectmodel import invoke_around_extcall, we_are_translated
+from pypy.module._stm import threadlocals, local
 
-
-class FakeWeakKeyDictionary:
-    # Only used if we don't have weakrefs.
-    # Then thread._local instances will leak, but too bad.
-    def __init__(self):
-        self.d = {}
-    def get(self, key):
-        return self.d.get(key, None)
-    def set(self, key, value):
-        self.d[key] = value
-
-
-def initialize_execution_context(ec):
-    """Called from ExecutionContext.__init__()."""
-    if ec.space.config.translation.rweakref:
-        from rpython.rlib import rweakref
-        ec._thread_local_dicts = rweakref.RWeakKeyDictionary(STMLocal, W_Root)
-    else:
-        ec._thread_local_dicts = FakeWeakKeyDictionary()
-    if ec.space.config.objspace.std.withmethodcache:
-        from pypy.objspace.std.typeobject import MethodCache
-        ec._methodcache = MethodCache(ec.space)
-
-def _fill_untranslated(ec):
-    if not we_are_translated() and not hasattr(ec, '_thread_local_dicts'):
-        initialize_execution_context(ec)
-
-
-class STMThreadLocals(OSThreadLocals):
-    threads_running = False
-    _immutable_fields_ = ['threads_running?']
-
-    def initialize(self, space):
-        """NOT_RPYTHON: set up a mechanism to send to the C code the value
-        set by space.actionflag.setcheckinterval()."""
-        #
-        def setcheckinterval_callback():
-            self.configure_transaction_length(space)
-        #
-        assert space.actionflag.setcheckinterval_callback is None
-        space.actionflag.setcheckinterval_callback = setcheckinterval_callback
-
-    # XXX?
-    #def getallvalues(self):
-    #    raise ValueError
-
-    def setup_threads(self, space):
-        if not self.threads_running:
-            # invalidate quasi-immutable if we have threads:
-            self.threads_running = True
-        self.configure_transaction_length(space)
-        invoke_around_extcall(rstm.before_external_call,
-                              rstm.after_external_call,
-                              rstm.enter_callback_call,
-                              rstm.leave_callback_call)
-
-    def configure_transaction_length(self, space):
-        if self.threads_running:
-            interval = space.actionflag.getcheckinterval()
-            rstm.set_transaction_length(interval / 10000.0)
-
-# ____________________________________________________________
-
-
-class STMLock(rthread.Lock):
-    def __init__(self, space, ll_lock):
-        rthread.Lock.__init__(self, ll_lock)
-        self.space = space
-
-    def acquire(self, flag):
-        if rstm.is_atomic():
-            acquired = rthread.Lock.acquire(self, False)
-            if flag and not acquired:
-                raise wrap_thread_error(self.space,
-                    "deadlock: an atomic transaction tries to acquire "
-                    "a lock that is already acquired.  See pypy/doc/stm.rst.")
-        else:
-            acquired = rthread.Lock.acquire(self, flag)
-        return acquired
-
-def allocate_stm_lock(space):
-    return STMLock(space, rthread.allocate_ll_lock())
-
-# ____________________________________________________________
-
-
-class STMLocal(W_Root):
-    """Thread-local data"""
-
-    @jit.dont_look_inside
-    def __init__(self, space, initargs):
-        self.space = space
-        self.initargs = initargs
-        # The app-level __init__() will be called by the general
-        # instance-creation logic.  It causes getdict() to be
-        # immediately called.  If we don't prepare and set a w_dict
-        # for the current thread, then this would in cause getdict()
-        # to call __init__() a second time.
-        ec = space.getexecutioncontext()
-        _fill_untranslated(ec)
-        w_dict = space.newdict(instance=True)
-        ec._thread_local_dicts.set(self, w_dict)
-
-    @jit.dont_look_inside
-    def create_new_dict(self, ec):
-        # create a new dict for this thread
-        space = self.space
-        w_dict = space.newdict(instance=True)
-        ec._thread_local_dicts.set(self, w_dict)
-        # call __init__
-        try:
-            w_self = space.wrap(self)
-            w_type = space.type(w_self)
-            w_init = space.getattr(w_type, space.wrap("__init__"))
-            space.call_obj_args(w_init, w_self, self.initargs)
-        except:
-            # failed, forget w_dict and propagate the exception
-            ec._thread_local_dicts.set(self, None)
-            raise
-        # ready
-        return w_dict
-
-    def getdict(self, space):
-        ec = space.getexecutioncontext()
-        _fill_untranslated(ec)
-        w_dict = ec._thread_local_dicts.get(self)
-        if w_dict is None:
-            w_dict = self.create_new_dict(ec)
-        return w_dict
-
-    def descr_local__new__(space, w_subtype, __args__):
-        local = space.allocate_instance(STMLocal, w_subtype)
-        STMLocal.__init__(local, space, __args__)
-        return space.wrap(local)
-
-    def descr_local__init__(self, space):
-        # No arguments allowed
-        pass
-
-STMLocal.typedef = TypeDef("thread._local",
-                     __doc__ = "Thread-local data",
-                     __new__ = interp2app(STMLocal.descr_local__new__.im_func),
-                     __init__ = interp2app(STMLocal.descr_local__init__),
-                     __dict__ = GetSetProperty(descr_get_dict, cls=STMLocal),
-                     )
+STMThreadLocals = threadlocals.STMThreadLocals
+STMLocal = local.STMLocal


More information about the pypy-commit mailing list