Ronny Pfannschmidt avatar Ronny Pfannschmidt committed a255c9e

introduce thread.exclusive_atomic

it will throw an error if it is used within another atomic block

Comments (0)

Files changed (4)

pypy/module/thread/__init__.py

 class Module(MixedModule):
     appleveldefs = {
         'atomic':                 'app_atomic.atomic',
+        'exclusive_atomic':       'app_atomic.exclusive_atomic',
     }
 
     interpleveldefs = {
         '_local':                 'os_local.Local',
         'error':                  'space.fromcache(error.Cache).w_error',
         '_atomic_enter':          'atomic.atomic_enter',
+        '_exclusive_atomic_enter': 'atomic.exclusive_atomic_enter',
         '_atomic_exit':           'atomic.atomic_exit',
     }
 

pypy/module/thread/app_atomic.py

     __enter__ = thread._atomic_enter
     __exit__  = thread._atomic_exit
 
+class ExclusiveAtomic(object):
+    __enter__ = thread._exclusive_atomic_enter
+    __exit__ = thread._atomic_exit
+
 atomic = Atomic()
+exclusive_atomic = ExclusiveAtomic()

pypy/module/thread/atomic.py

 from pypy.interpreter.error import OperationError
 from pypy.module.thread.error import wrap_thread_error
 
+
+
+def exclusive_atomic_enter(space):
+    if space.config.translation.stm:
+        from pypy.rlib.rstm import is_atomic
+        count = is_atomic()
+    else:
+        giltl = space.threadlocals
+        count = giltl.is_atomic
+    if count:
+        raise wrap_thread_error(space,
+            "exclusive_atomic block can't be entered inside another atomic block")
+
+    atomic_enter(space)
+
 def atomic_enter(space):
     if space.config.translation.stm:
         from pypy.rlib.rstm import increment_atomic

pypy/module/thread/test/test_atomic.py

 
     def test_simple(self):
         import thread
+        for atomic in thread.atomic, thread.exclusive_atomic:
+            with atomic:
+                pass
+            try:
+                with atomic:
+                    raise ValueError
+            except ValueError:
+                pass
+
+    def test_nest_composable_atomic(self):
+        import thread
         with thread.atomic:
-            pass
+            with thread.atomic:
+                pass
+
+    def test_nest_composable_below_exclusive(self):
+        import thread
+        with thread.exclusive_atomic:
+            with thread.atomic:
+                with thread.atomic:
+                    pass
+
+    def test_nest_exclusive_fails(self):
+        import thread
+        try:
+            with thread.exclusive_atomic:
+                with thread.exclusive_atomic:
+                    pass
+        except thread.error, e:
+            assert e.message == "exclusive_atomic block can't be entered inside another atomic block"
+
+    def test_nest_exclusive_fails2(self):
+        import thread
         try:
             with thread.atomic:
-                raise ValueError
-        except ValueError:
-            pass
+                with thread.exclusive_atomic:
+                    pass
+        except thread.error, e:
+            assert e.message == "exclusive_atomic block can't be entered inside another atomic block"
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.