[pypy-svn] r16363 - in pypy/dist/pypy: interpreter lib module/thread module/thread/test objspace/std

arigo at codespeak.net arigo at codespeak.net
Wed Aug 24 13:33:06 CEST 2005


Author: arigo
Date: Wed Aug 24 13:33:02 2005
New Revision: 16363

Added:
   pypy/dist/pypy/module/thread/test/test_import_lock.py   (contents, props changed)
Modified:
   pypy/dist/pypy/interpreter/baseobjspace.py
   pypy/dist/pypy/interpreter/module.py
   pypy/dist/pypy/lib/imp.py
   pypy/dist/pypy/module/thread/__init__.py
   pypy/dist/pypy/objspace/std/objspace.py
Log:
Implemented the import lock when --usemodules=thread.
The import lock itself is completely done at app-level in imp.py, to provide
the required interface imp.*lock*() to user programs.  It's done as an
__import__ hook.  There is a minor hack to force imp.py to get imported when
the space is done being initialized.
 --This line, and those below, will be ignored--

M    pypy/interpreter/baseobjspace.py
M    pypy/interpreter/module.py
AM   pypy/module/thread/test/test_import_lock.py
M    pypy/module/thread/__init__.py
M    pypy/objspace/std/objspace.py
M    pypy/lib/imp.py


Modified: pypy/dist/pypy/interpreter/baseobjspace.py
==============================================================================
--- pypy/dist/pypy/interpreter/baseobjspace.py	(original)
+++ pypy/dist/pypy/interpreter/baseobjspace.py	Wed Aug 24 13:33:02 2005
@@ -219,6 +219,12 @@
                 #print "setitem: space instance %-20s into builtins" % name
                 self.setitem(self.builtin.w_dict, self.wrap(name), value)
 
+    def setup_builtin_modules(self):
+        "NOT_RPYTHON: only for initializing the space."
+        for modname, mixedname in self.get_builtinmodule_list():
+            mod = self.getbuiltinmodule(modname)
+            mod.setup_after_space_initialization()
+
     def initialize(self):
         """NOT_RPYTHON: Abstract method that should put some minimal
         content into the w_builtins."""

Modified: pypy/dist/pypy/interpreter/module.py
==============================================================================
--- pypy/dist/pypy/interpreter/module.py	(original)
+++ pypy/dist/pypy/interpreter/module.py	Wed Aug 24 13:33:02 2005
@@ -17,6 +17,10 @@
         if w_name is not None:
             space.setitem(w_dict, space.wrap('__name__'), w_name) 
 
+    def setup_after_space_initialization(self):
+        """NOT_RPYTHON: to allow built-in modules to do some more setup
+        after the space is fully initialized."""
+
     def getdict(self):
         return self.w_dict
 

Modified: pypy/dist/pypy/lib/imp.py
==============================================================================
--- pypy/dist/pypy/lib/imp.py	(original)
+++ pypy/dist/pypy/lib/imp.py	Wed Aug 24 13:33:02 2005
@@ -7,8 +7,6 @@
 
 # XXX to be reviewed
 
-import sys, os
-
 PY_SOURCE       = 1
 PY_COMPILED     = 2
 C_EXTENSION     = 3
@@ -24,10 +22,9 @@
 def get_suffixes():
     return [('.py', 'U', PY_SOURCE)]
 
-new_module = type(sys)
-
 
 def find_module(name, path=None):
+    import sys, os
     if path is None:
         if name in sys.builtin_module_names:
             return (None, name, ('', '', C_BUILTIN))
@@ -43,6 +40,8 @@
 
 
 def load_module(name, file, filename, description):
+    import sys, os
+    new_module = type(sys)
     suffix, mode, type = description
     module = sys.modules.get(name)
 
@@ -75,10 +74,61 @@
     raise ValueError, 'invalid description argument: %r' % (description,)
 
 
-# XXX needs to be implemented when we have threads
-def lock_held():
-    return False
-def acquire_lock():
-    pass
-def release_lock():
-    pass
+try:
+    # PyPy-specific interface: hint from the thread module to ask us to
+    # provide an import lock
+    from thread import _please_provide_import_lock
+except ImportError:
+    def lock_held():
+        return False
+    def acquire_lock():
+        pass
+    def release_lock():
+        pass
+else:
+    del _please_provide_import_lock
+    import thread
+
+    class _ImportLock:
+        def __init__(self):
+            self.lock = thread.allocate_lock()
+            self.in_thread = None
+            self.recursions = 0
+
+        def held(self):
+            return self.in_thread is not None
+
+        def acquire(self):
+            myident = thread.get_ident()
+            if self.in_thread == myident:
+                self.recursions += 1
+            else:
+                self.lock.acquire()
+                self.in_thread = myident
+                self.recursions = 1
+
+        def release(self):
+            myident = thread.get_ident()
+            if self.in_thread != myident:
+                raise RuntimeError("not holding the import lock")
+            self.recursions -= 1
+            if self.recursions == 0:
+                self.in_thread = None
+                self.lock.release()
+
+    _importlock = _ImportLock()
+
+    lock_held    = _importlock.held
+    acquire_lock = _importlock.acquire
+    release_lock = _importlock.release
+
+    import __builtin__
+    _original_import_hook = __builtin__.__import__
+    def __lockedimport__(modulename, globals=None, locals=None, fromlist=None):
+        acquire_lock()
+        try:
+            return _original_import_hook(modulename, globals, locals, fromlist)
+        finally:
+            release_lock()
+    __builtin__.__import__ = __lockedimport__
+    del __builtin__

Modified: pypy/dist/pypy/module/thread/__init__.py
==============================================================================
--- pypy/dist/pypy/module/thread/__init__.py	(original)
+++ pypy/dist/pypy/module/thread/__init__.py	Wed Aug 24 13:33:02 2005
@@ -16,6 +16,7 @@
         'allocate':               'os_lock.allocate_lock',  # obsolete synonym
         'LockType':               'os_lock.getlocktype(space)',
         '_local':                 'os_local.getlocaltype(space)',
+        '_please_provide_import_lock': '(space.w_True)',   # for imp.py
     }
 
     def __init__(self, space, *args):
@@ -26,3 +27,9 @@
         space.threadlocals = gil.GILThreadLocals()
         space.threadlocals.setvalue(prev)
         space.threadlocals.enter_thread(space)   # setup the main thread
+
+    def setup_after_space_initialization(self):
+        # the import lock is in imp.py.  Import it after the space is fully
+        # initialized.
+        from pypy.module.__builtin__.importing import importhook
+        importhook(self.space, 'imp')

Added: pypy/dist/pypy/module/thread/test/test_import_lock.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/module/thread/test/test_import_lock.py	Wed Aug 24 13:33:02 2005
@@ -0,0 +1,15 @@
+from pypy.module.thread.test.support import GenericTestThread
+
+
+class AppTestThread(GenericTestThread):
+
+    def test_import_lock(self):
+        import thread
+        done = []
+        def f():
+            from imghdr import testall
+            done.append(1)
+        for i in range(5):
+            thread.start_new_thread(f, ())
+        self.waitfor(lambda: len(done) == 5)
+        assert len(done) == 5

Modified: pypy/dist/pypy/objspace/std/objspace.py
==============================================================================
--- pypy/dist/pypy/objspace/std/objspace.py	(original)
+++ pypy/dist/pypy/objspace/std/objspace.py	Wed Aug 24 13:33:02 2005
@@ -107,6 +107,9 @@
         if self.options.oldstyle: 
             self.enable_old_style_classes_as_default_metaclass()
 
+        # final setup
+        self.setup_builtin_modules()
+
     def enable_old_style_classes_as_default_metaclass(self):
         self.setitem(self.builtin.w_dict, self.wrap('__metaclass__'), self.w_classobj)
 



More information about the Pypy-commit mailing list