[pypy-svn] r54893 - in pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk: . test

tverwaes at codespeak.net tverwaes at codespeak.net
Sun May 18 17:22:45 CEST 2008


Author: tverwaes
Date: Sun May 18 17:22:45 2008
New Revision: 54893

Modified:
   pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/error.py
   pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_wrapper.py
   pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/wrapper.py
Log:
(cfbolz, tverwaes) add suspend, signal, highest_priority_process and wait. Add
way to signal fatal and wrapper errors with messages


Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/error.py
==============================================================================
--- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/error.py	(original)
+++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/error.py	Sun May 18 17:22:45 2008
@@ -15,3 +15,10 @@
 class WrappingError(PrimitiveFailedError):
     pass
 
+class WrapperException(SmalltalkException):
+    def __init__(self, msg):
+        self.msg = msg
+
+class FatalError(SmalltalkException):
+    def __init__(self, msg):
+        self.msg = msg

Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_wrapper.py
==============================================================================
--- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_wrapper.py	(original)
+++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_wrapper.py	Sun May 18 17:22:45 2008
@@ -3,6 +3,7 @@
 from pypy.lang.smalltalk import model
 from pypy.lang.smalltalk import objtable, utility
 from pypy.lang.smalltalk import interpreter
+from pypy.lang.smalltalk.error import WrapperException, FatalError
 
 def test_simpleread():
     w_o = model.W_PointersObject(None, 2)
@@ -11,8 +12,8 @@
     assert w.read(0) == "hello"
     w.write(1, "b")
     assert w.read(1) == "b"
-    py.test.raises(IndexError, "w.read(2)")
-    py.test.raises(IndexError, "w.write(2, \"test\")")
+    py.test.raises(WrapperException, "w.read(2)")
+    py.test.raises(WrapperException, "w.write(2, \"test\")")
 
 def test_accessor_generators():
     w_o = model.W_PointersObject(None, 1)
@@ -102,7 +103,11 @@
     scheduler.write(0, priority_list.w_self)
     return scheduler
 
-
+def new_semaphore(excess_signals=0):
+    w_semaphore = model.W_PointersObject(None, 3)
+    semaphore = wrapper.SemaphoreWrapper(w_semaphore)
+    semaphore.store_excess_signals(utility.wrap_int(excess_signals))
+    return semaphore
 
 class TestScheduler(object):
     def setup_method(self, meth):
@@ -120,12 +125,9 @@
         assert process_list.first_link() is process_list.last_link()
         assert process_list.first_link() is process.w_self
 
-    def old_new_process_consistency(self, process, old_process, interp,
+    def new_process_consistency(self, process, old_process, interp,
                                     old_active_context, new_active_context):
         scheduler = wrapper.scheduler()
-        assert old_process.suspended_context() is old_active_context
-        priority_list = scheduler.get_process_list(old_process.priority())
-        assert priority_list.first_link() is old_process.w_self
         assert interp.w_active_context() is new_active_context
         assert scheduler.active_process() is process.w_self
         priority_list = wrapper.scheduler().get_process_list(process.priority())
@@ -134,35 +136,64 @@
         # The caller of activate is responsible
         assert priority_list.first_link() is process.w_self
 
-    def test_activate(self):
+    def old_process_consistency(self, old_process, old_process_context):
+        assert old_process.suspended_context() is old_process_context
+        priority_list = wrapper.scheduler().get_process_list(old_process.priority())
+        assert priority_list.first_link() is old_process.w_self
+
+    def make_processes(self, sleepingpriority, runningpriority,
+                             sleepingcontext, runningcontext):
         interp = interpreter.Interpreter()
         scheduler = wrapper.scheduler()
-        process = new_process(priority=2, w_suspended_context=objtable.w_false)
-        process.put_to_sleep()
-        old_process = new_process(priority=3)
-        scheduler.store_active_process(old_process.w_self)
-        interp.store_w_active_context(objtable.w_true)
-        process.activate(interp)
+        sleeping = new_process(priority=sleepingpriority,
+                               w_suspended_context=sleepingcontext)
+        sleeping.put_to_sleep()
+        running = new_process(priority=runningpriority)
+        scheduler.store_active_process(running.w_self)
+        interp.store_w_active_context(runningcontext)
+
+        return interp, sleeping, running
+
 
-        self.old_new_process_consistency(process, old_process, interp,
+    def test_activate(self):
+        interp, process, old_process = self.make_processes(4, 2, objtable.w_false, objtable.w_true)
+        process.activate(interp)
+        self.new_process_consistency(process, old_process, interp,
                                          objtable.w_true, objtable.w_false)
        
     def test_resume(self):
-        interp = interpreter.Interpreter()
-        scheduler = wrapper.scheduler()
-        process = new_process(priority=4, w_suspended_context=objtable.w_false)
-        process.put_to_sleep()
-        old_process = new_process(priority=2)
-        scheduler.store_active_process(old_process.w_self)
-        interp.store_w_active_context(objtable.w_true)
-
+        interp, process, old_process = self.make_processes(4, 2, objtable.w_false, objtable.w_true)
         process.resume(interp)
-        self.old_new_process_consistency(process, old_process, interp,
+        self.new_process_consistency(process, old_process, interp,
                                          objtable.w_true, objtable.w_false)
+        self.old_process_consistency(old_process, objtable.w_true)
 
         # Does not reactivate old_process because lower priority
         old_process.resume(interp)
-        self.old_new_process_consistency(process, old_process, interp,
+        self.new_process_consistency(process, old_process, interp,
                                          objtable.w_true, objtable.w_false)
+        self.old_process_consistency(old_process, objtable.w_true)
 
-
+    def test_semaphore_excess_signal(self):
+        semaphore = new_semaphore()
+        
+        semaphore.signal(None)
+        assert utility.unwrap_int(semaphore.excess_signals()) == 1
+
+    def test_highest_priority(self):
+        py.test.raises(FatalError, wrapper.scheduler().highest_priority_process)
+        interp, process, old_process = self.make_processes(4, 2, objtable.w_false, objtable.w_true)
+        process.put_to_sleep()
+        old_process.put_to_sleep()
+        highest = wrapper.scheduler().highest_priority_process()
+        assert highest is process.w_self
+        highest = wrapper.scheduler().highest_priority_process()
+        assert highest is old_process.w_self
+        py.test.raises(FatalError, wrapper.scheduler().highest_priority_process)
+
+    def test_semaphore_wait(self):
+        semaphore = new_semaphore()
+        interp, process, old_process = self.make_processes(4, 2, objtable.w_false, objtable.w_true)
+        semaphore.wait(interp)
+        assert semaphore.first_link() is old_process.w_self
+        assert wrapper.scheduler().active_process() is process.w_self

Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/wrapper.py
==============================================================================
--- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/wrapper.py	(original)
+++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/wrapper.py	Sun May 18 17:22:45 2008
@@ -1,24 +1,24 @@
 from pypy.lang.smalltalk import model
-from pypy.lang.smalltalk import utility
+from pypy.lang.smalltalk import utility, objtable
+from pypy.lang.smalltalk.error import FatalError, WrapperException
 
 class Wrapper(object):
     def __init__(self, w_self):
-        assert isinstance(w_self, model.W_PointersObject)
+        if not isinstance(w_self, model.W_PointersObject):
+            raise WrapperException("Unexpected instance given to wrapper")
         self.w_self = w_self
 
     def read(self, index0):
         try:
             return self.w_self._vars[index0]
         except IndexError:
-            # XXX nicer errormessage
-            raise
+            raise WrapperException("Unexpected instance layout. Too small")
 
     def write(self, index0, w_new):
         try:
             self.w_self._vars[index0] = w_new
         except IndexError:
-            # XXX nicer errormessage
-            raise
+            raise WrapperException("Unexpected instance layout. Too small")
 
 def make_getter(index0):
     def getter(self):
@@ -53,24 +53,32 @@
     def activate(self, interp):
         from pypy.lang.smalltalk import objtable
         sched = scheduler()
-        w_old_process = sched.active_process()
         sched.store_active_process(self.w_self)
-        old_process = ProcessWrapper(w_old_process)
-        old_process.store_suspended_context(interp.w_active_context())
-        old_process.put_to_sleep()
         interp.store_w_active_context(self.suspended_context())
         self.store_suspended_context(objtable.w_nil)
 
+    def deactivate(self, interp):
+        self.put_to_sleep()
+        self.store_suspended_context(interp.w_active_context())
+
     def resume(self, interp):
         sched = scheduler()
         active_process = ProcessWrapper(sched.active_process())
         active_priority = active_process.priority()
         priority = self.priority()
         if priority > active_priority:
+            active_process.deactivate(interp)
             self.activate(interp)
         else:
             self.put_to_sleep()
 
+    def is_active_process(self):
+        return self.w_self is scheduler().active_process()
+
+    def suspend(self, interp):
+        assert self.is_active_process()
+        assert self.my_list() is objtable.w_nil
+        ProcessWrapper(scheduler().highest_priority_process()).activate(interp)
 
 class LinkedListWrapper(Wrapper):
     first_link, store_first_link = make_getter_setter(0)
@@ -117,6 +125,18 @@
         lists = self.priority_list()
         return ProcessListWrapper(Wrapper(lists).read(priority))
 
+    def highest_priority_process(self):
+        w_lists = self.priority_list()
+        # Asserts as W_PointersObject
+        lists = Wrapper(w_lists)
+        
+        for i in range(len(w_lists._vars) -1, -1, -1):
+            process_list = ProcessListWrapper(lists.read(i))
+            if not process_list.is_empty_list():
+                return process_list.remove_first_link_of_list()
+
+        raise FatalError("Scheduler could not find a runnable process")
+
 def scheduler():
     from pypy.lang.smalltalk import objtable
     w_association = objtable.objtable["w_schedulerassociationpointer"]
@@ -127,7 +147,7 @@
 
 class SemaphoreWrapper(LinkedListWrapper):
 
-    excess_signals, store_excess_signals = make_getter_setter(0)
+    excess_signals, store_excess_signals = make_getter_setter(2)
 
     def signal(self, interp):
         if self.is_empty_list():
@@ -135,13 +155,14 @@
             w_value = utility.wrap_int(utility.unwrap_int(w_value) + 1)
             self.store_excess_signals(w_value)
         else:
-            self.resume(self.remove_first_link_of_list(), interp)
+            self.remove_first_link_of_list().resume(interp)
 
-    def wait(self, w_process, interp):
+    def wait(self, interp):
         excess = utility.unwrap_int(self.excess_signals())
+        w_process = scheduler().active_process()
         if excess > 0:
             w_excess = utility.wrap_int(excess - 1)
             self.store_excess_signals(w_excess)
         else:
             self.add_last_link(w_process)
-            ProcessWrapper(w_process).put_to_sleep()
+            ProcessWrapper(w_process).suspend(interp)



More information about the Pypy-commit mailing list