[pypy-svn] r56132 - in pypy/branch/async-del/pypy/module/thread: . test

arigo at codespeak.net arigo at codespeak.net
Fri Jun 27 19:17:51 CEST 2008


Author: arigo
Date: Fri Jun 27 19:17:51 2008
New Revision: 56132

Modified:
   pypy/branch/async-del/pypy/module/thread/__init__.py
   pypy/branch/async-del/pypy/module/thread/gil.py
   pypy/branch/async-del/pypy/module/thread/test/test_gil.py
   pypy/branch/async-del/pypy/module/thread/threadlocals.py
Log:
Some progress in the thread module.


Modified: pypy/branch/async-del/pypy/module/thread/__init__.py
==============================================================================
--- pypy/branch/async-del/pypy/module/thread/__init__.py	(original)
+++ pypy/branch/async-del/pypy/module/thread/__init__.py	Fri Jun 27 19:17:51 2008
@@ -30,4 +30,5 @@
         MixedModule.__init__(self, space, *args)
         prev = space.threadlocals.getvalue()
         space.threadlocals = gil.GILThreadLocals()
+        space.threadlocals.initialize(space)
         space.threadlocals.setvalue(prev)

Modified: pypy/branch/async-del/pypy/module/thread/gil.py
==============================================================================
--- pypy/branch/async-del/pypy/module/thread/gil.py	(original)
+++ pypy/branch/async-del/pypy/module/thread/gil.py	Fri Jun 27 19:17:51 2008
@@ -9,7 +9,7 @@
 
 from pypy.module.thread import ll_thread as thread
 from pypy.module.thread.error import wrap_thread_error
-from pypy.interpreter.miscutils import Action
+from pypy.interpreter.executioncontext import PeriodicAsyncAction
 from pypy.module.thread.threadlocals import OSThreadLocals
 from pypy.rlib.objectmodel import invoke_around_extcall
 from pypy.rlib.rposix import get_errno, set_errno
@@ -18,6 +18,10 @@
     """A version of OSThreadLocals that enforces a GIL."""
     ll_GIL = thread.null_ll_lock
 
+    def initialize(self, space):
+        # add the GIL-releasing callback as an action on the space
+        space.actionflag.register_action(GILReleaseAction(space))
+
     def setup_threads(self, space):
         """Enable threads in the object space, if they haven't already been."""
         if not self.ll_GIL:
@@ -27,8 +31,6 @@
                 raise wrap_thread_error(space, "can't allocate GIL")
             thread.acquire_NOAUTO(self.ll_GIL, True)
             self.enter_thread(space)   # setup the main thread
-            # add the GIL-releasing callback as an action on the space
-            space.pending_actions.append(GILReleaseAction(self))
             result = True
         else:
             result = False      # already set up
@@ -47,25 +49,19 @@
         return result
 
     def yield_thread(self):
-        """Notification that the current thread is between two bytecodes:
-        release the GIL for a little while."""
-        # Other threads can run between the release() and the acquire()
-        # implicit in the following external function call (which has
-        # otherwise no effect).
-        thread.yield_thread()
+        thread.yield_thread()  # explicitly release the gil (used by test_gil)
 
 
-class GILReleaseAction(Action):
-    """An action called when the current thread is between two bytecodes
-    (so that it's a good time to yield some time to other threads).
+class GILReleaseAction(PeriodicAsyncAction):
+    """An action called every sys.checkinterval bytecodes.  It releases
+    the GIL to give some other thread a chance to run.
     """
-    repeat = True
 
-    def __init__(self, threadlocals):
-        self.threadlocals = threadlocals
-
-    def perform(self):
-        self.threadlocals.yield_thread()
+    def perform(self, executioncontext):
+        # Other threads can run between the release() and the acquire()
+        # implicit in the following external function call (which has
+        # otherwise no effect).
+        thread.yield_thread()
 
 
 class SpaceState:
@@ -86,6 +82,7 @@
             actionflag.set(flag)
 
 spacestate = SpaceState()
+spacestate._freeze_()
 
 # Fragile code below.  We have to preserve the C-level errno manually...
 

Modified: pypy/branch/async-del/pypy/module/thread/test/test_gil.py
==============================================================================
--- pypy/branch/async-del/pypy/module/thread/test/test_gil.py	(original)
+++ pypy/branch/async-del/pypy/module/thread/test/test_gil.py	Fri Jun 27 19:17:51 2008
@@ -8,9 +8,17 @@
 class FakeEC(object):
     pass
 
+class FakeActionFlag(object):
+    def register_action(self, action):
+        pass
+    def get(self):
+        return 0
+    def set(self, x):
+        pass
+
 class FakeSpace(object):
     def __init__(self):
-        self.pending_actions = []
+        self.actionflag = FakeActionFlag()
     def _freeze_(self):
         return True
     def getexecutioncontext(self):

Modified: pypy/branch/async-del/pypy/module/thread/threadlocals.py
==============================================================================
--- pypy/branch/async-del/pypy/module/thread/threadlocals.py	(original)
+++ pypy/branch/async-del/pypy/module/thread/threadlocals.py	Fri Jun 27 19:17:51 2008
@@ -7,6 +7,7 @@
     os_thread.bootstrap()."""
 
     def __init__(self):
+        print 'FRESH NEW THREADLOCALS'
         self._valuedict = {}   # {thread_ident: ExecutionContext()}
         self._mainthreadident = 0
         self._mostrecentkey = 0        # fast minicaching for the common case
@@ -15,16 +16,20 @@
     def getvalue(self):
         ident = thread.get_ident()
         if ident == self._mostrecentkey:
-            return self._mostrecentvalue
+            result = self._mostrecentvalue
+            print '(cached)',
         else:
             value = self._valuedict.get(ident, None)
             # slow path: update the minicache
             self._mostrecentkey = ident
             self._mostrecentvalue = value
-            return value
+            result = value
+        print '%d => %r' % (ident, result)
+        return result
 
     def setvalue(self, value):
         ident = thread.get_ident()
+        print 'SET %d => %r' % (ident, value)
         if value is not None:
             if len(self._valuedict) == 0:
                 self._mainthreadident = ident
@@ -37,6 +42,7 @@
         # update the minicache to prevent it from containing an outdated value
         self._mostrecentkey = ident
         self._mostrecentvalue = value
+        print self._valuedict
 
     def getmainthreadvalue(self):
         ident = self._mainthreadident
@@ -45,21 +51,19 @@
     def enter_thread(self, space):
         "Notification that the current thread is just starting."
         ec = space.getexecutioncontext()
+        print 'ENTER_THREAD', thread.get_ident(), ec
         ec.thread_exit_funcs = []
 
     def leave_thread(self, space):
         "Notification that the current thread is about to stop."
         try:
             ec = space.getexecutioncontext()
+            print 'LEAVE_THREAD', thread.get_ident(), ec
             while ec.thread_exit_funcs:
                 exit_func, w_obj = ec.thread_exit_funcs.pop()
                 exit_func(w_obj)
         finally:
-            ident = thread.get_ident()
-            try:
-                del self._valuedict[ident]
-            except KeyError:
-                pass
+            self.setvalue(None)
 
     def atthreadexit(self, space, exit_func, w_obj):
         ec = space.getexecutioncontext()



More information about the Pypy-commit mailing list