瀏覽代碼

timers are now local to sccd class instances

Simon Van Mierlo 8 年之前
父節點
當前提交
b69426f0ea

+ 160 - 0
examples/my-tests/python/multiple_raises_parallel.py

@@ -0,0 +1,160 @@
+"""
+Generated by Statechart compiler by Glenn De Jonghe, Joeri Exelmans, Simon Van Mierlo, and Yentl Van Tendeloo (for the inspiration)
+
+Date:   Fri Jul 28 15:14:50 2017
+
+Model name:   multiple-raises-parallel
+
+"""
+
+from sccd.runtime.statecharts_core import *
+
+# package "multiple-raises-parallel"
+
+class A(RuntimeClassBase):
+    def __init__(self, controller):
+        RuntimeClassBase.__init__(self, controller)
+        
+        self.semantics.big_step_maximality = StatechartSemantics.TakeOne
+        self.semantics.internal_event_lifeline = StatechartSemantics.Queue
+        self.semantics.input_event_lifeline = StatechartSemantics.FirstComboStep
+        self.semantics.priority = StatechartSemantics.SourceParent
+        self.semantics.concurrency = StatechartSemantics.Single
+        
+        # build Statechart structure
+        self.build_statechart_structure()
+        
+        # call user defined constructor
+        A.user_defined_constructor(self)
+    
+    def user_defined_constructor(self):
+        pass
+    
+    def user_defined_destructor(self):
+        pass
+    
+    
+    # builds Statechart structure
+    def build_statechart_structure(self):
+        
+        # state <root>
+        self.states[""] = State(0, "", self)
+        
+        # state /x
+        self.states["/x"] = ParallelState(1, "/x", self)
+        
+        # state /x/x1
+        self.states["/x/x1"] = State(2, "/x/x1", self)
+        
+        # state /x/x1/x1
+        self.states["/x/x1/x1"] = State(3, "/x/x1/x1", self)
+        
+        # state /x/x1/end
+        self.states["/x/x1/end"] = State(4, "/x/x1/end", self)
+        
+        # state /x/x2
+        self.states["/x/x2"] = State(5, "/x/x2", self)
+        
+        # state /x/x2/x2
+        self.states["/x/x2/x2"] = State(6, "/x/x2/x2", self)
+        
+        # state /x/x2/end
+        self.states["/x/x2/end"] = State(7, "/x/x2/end", self)
+        
+        # state /x/x3
+        self.states["/x/x3"] = State(8, "/x/x3", self)
+        
+        # state /x/x3/x3
+        self.states["/x/x3/x3"] = State(9, "/x/x3/x3", self)
+        
+        # state /x/x3/end
+        self.states["/x/x3/end"] = State(10, "/x/x3/end", self)
+        
+        # state /x/receiving
+        self.states["/x/receiving"] = State(11, "/x/receiving", self)
+        
+        # state /x/receiving/receiving
+        self.states["/x/receiving/receiving"] = State(12, "/x/receiving/receiving", self)
+        
+        # add children
+        self.states[""].addChild(self.states["/x"])
+        self.states["/x"].addChild(self.states["/x/x1"])
+        self.states["/x"].addChild(self.states["/x/x2"])
+        self.states["/x"].addChild(self.states["/x/x3"])
+        self.states["/x"].addChild(self.states["/x/receiving"])
+        self.states["/x/x1"].addChild(self.states["/x/x1/x1"])
+        self.states["/x/x1"].addChild(self.states["/x/x1/end"])
+        self.states["/x/x2"].addChild(self.states["/x/x2/x2"])
+        self.states["/x/x2"].addChild(self.states["/x/x2/end"])
+        self.states["/x/x3"].addChild(self.states["/x/x3/x3"])
+        self.states["/x/x3"].addChild(self.states["/x/x3/end"])
+        self.states["/x/receiving"].addChild(self.states["/x/receiving/receiving"])
+        self.states[""].fixTree()
+        self.states[""].default_state = self.states["/x"]
+        self.states["/x/x1"].default_state = self.states["/x/x1/x1"]
+        self.states["/x/x2"].default_state = self.states["/x/x2/x2"]
+        self.states["/x/x3"].default_state = self.states["/x/x3/x3"]
+        self.states["/x/receiving"].default_state = self.states["/x/receiving/receiving"]
+        
+        # transition /x/x1/x1
+        _x_x1_x1_0 = Transition(self, self.states["/x/x1/x1"], [self.states["/x/x1/end"]])
+        _x_x1_x1_0.setAction(self._x_x1_x1_0_exec)
+        _x_x1_x1_0.setTrigger(None)
+        self.states["/x/x1/x1"].addTransition(_x_x1_x1_0)
+        
+        # transition /x/x2/x2
+        _x_x2_x2_0 = Transition(self, self.states["/x/x2/x2"], [self.states["/x/x2/end"]])
+        _x_x2_x2_0.setAction(self._x_x2_x2_0_exec)
+        _x_x2_x2_0.setTrigger(None)
+        self.states["/x/x2/x2"].addTransition(_x_x2_x2_0)
+        
+        # transition /x/x3/x3
+        _x_x3_x3_0 = Transition(self, self.states["/x/x3/x3"], [self.states["/x/x3/end"]])
+        _x_x3_x3_0.setAction(self._x_x3_x3_0_exec)
+        _x_x3_x3_0.setTrigger(None)
+        self.states["/x/x3/x3"].addTransition(_x_x3_x3_0)
+        
+        # transition /x/receiving/receiving
+        _x_receiving_receiving_0 = Transition(self, self.states["/x/receiving/receiving"], [self.states["/x/receiving/receiving"]])
+        _x_receiving_receiving_0.setAction(self._x_receiving_receiving_0_exec)
+        _x_receiving_receiving_0.setTrigger(Event("z", None))
+        self.states["/x/receiving/receiving"].addTransition(_x_receiving_receiving_0)
+    
+    def _x_x1_x1_0_exec(self, parameters):
+        self.raiseInternalEvent(Event("z", None, []))
+        print 'raised event in x1'
+    
+    def _x_x2_x2_0_exec(self, parameters):
+        self.raiseInternalEvent(Event("z", None, []))
+        print 'raised event in x2'
+    
+    def _x_x3_x3_0_exec(self, parameters):
+        self.raiseInternalEvent(Event("z", None, []))
+        print 'raised event in x3'
+    
+    def _x_receiving_receiving_0_exec(self, parameters):
+        print 'received event...'
+    
+    def initializeStatechart(self):
+        # enter default state
+        self.default_targets = self.states["/x"].getEffectiveTargetStates()
+        RuntimeClassBase.initializeStatechart(self)
+
+class ObjectManager(ObjectManagerBase):
+    def __init__(self, controller):
+        ObjectManagerBase.__init__(self, controller)
+    
+    def instantiate(self, class_name, construct_params):
+        if class_name == "A":
+            instance = A(self.controller)
+            instance.associations = {}
+        else:
+            raise Exception("Cannot instantiate class " + class_name)
+        return instance
+
+class Controller(ThreadsControllerBase):
+    def __init__(self, keep_running = None, behind_schedule_callback = None):
+        if keep_running == None: keep_running = True
+        if behind_schedule_callback == None: behind_schedule_callback = None
+        ThreadsControllerBase.__init__(self, ObjectManager(self), keep_running, behind_schedule_callback)
+        self.object_manager.createInstance("A", [])

+ 51 - 0
examples/my-tests/python/multiple_raises_parallel.xml

@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<diagram name="multiple-raises-parallel">
+    <class name="A" default="true">
+        <scxml big_step_maximality="take_one" initial="x">
+            <parallel id="x">
+                <state id="x1" initial="x1">
+                    <state id="x1">
+                        <transition target="../end">
+                            <raise event="z" />
+                            <script>
+                                print 'raised event in x1'
+                            </script>
+                        </transition>
+                    </state>
+                    <state id="end" />
+                </state>
+                <state id="x2" initial="x2">
+                    <state id="x2">
+                        <transition target="../end">
+                            <raise event="z" />
+                            <script>
+                                print 'raised event in x2'
+                            </script>
+                        </transition>
+                    </state>
+                    <state id="end" />
+                </state>
+                <state id="x3" initial="x3">
+                    <state id="x3">
+                        <transition target="../end">
+                            <raise event="z" />
+                            <script>
+                                print 'raised event in x3'
+                            </script>
+                        </transition>
+                    </state>
+                    <state id="end" />
+                </state>
+                <state id="receiving">
+                    <state id="receiving">
+                        <transition target="." event="z">
+                            <script>
+                                print 'received event...'
+                            </script>
+                        </transition>
+                    </state>
+                </state>
+            </parallel>
+        </scxml>
+    </class>
+</diagram>

+ 3 - 0
examples/my-tests/python/runner_multiple_raises_parallel.py

@@ -0,0 +1,3 @@
+import multiple_raises_parallel
+controller = multiple_raises_parallel.Controller(False)
+controller.start()

+ 2 - 5
examples/timer-parallel/python/sccd.xml

@@ -2,9 +2,6 @@
 <diagram author="Simon Van Mierlo" name="Timer (Threaded Version)">
     <description>
     </description>
-    <top>
-        from sccd.runtime.accurate_time import time
-    </top>    
     <inport name="input" />
 
     <class name="MainApp" default="true">
@@ -16,12 +13,12 @@
         </method>
         <method name="print_simulated_time">
             <body>
-                print 'SIMTIME = %.2f' % get_simulated_time()
+                print 'SIMTIME = %.2f' % self.getSimulatedTime()
             </body>
         </method>
         <method name="print_wct_time">
             <body>
-                print 'ACTTIME = %.2f' % time()
+                print 'ACTTIME = %.2f' % self.getWallClockTime()
             </body>
         </method>
         <scxml initial="running">

+ 5 - 9
examples/timer-threads/python/sccd.xml

@@ -1,9 +1,5 @@
 <?xml version="1.0" ?>
-<diagram author="Simon Van Mierlo" name="Timer (Threaded Version)">
-    <top>
-        from sccd.runtime.accurate_time import time
-    </top>
-    
+<diagram author="Simon Van Mierlo" name="Timer (Threaded Version)">    
     <inport name="input" />        
     <outport name="output" />
 
@@ -13,13 +9,13 @@
                 <transition target="." after="0.05">
                     <raise event="time_update" port="output">
                         <parameter expr="self.getSimulatedTime()" />
-                        <parameter expr="time()" />
+                        <parameter expr="self.getWallClockTime()" />
                     </raise>
                 </transition>
                 <transition target="../interrupted" event="interrupt" port="input">
                     <raise event="time_update" port="output">
                         <parameter expr="self.getSimulatedTime()" />
-                        <parameter expr="time()" />
+                        <parameter expr="self.getWallClockTime()" />
                     </raise>
                 </transition>
             </state>
@@ -27,13 +23,13 @@
                 <transition target="." event="interrupt" port="input">
                     <raise event="time_update" port="output">
                         <parameter expr="self.getSimulatedTime()" />
-                        <parameter expr="time()" />
+                        <parameter expr="self.getWallClockTime()" />
                     </raise>
                 </transition>
                 <transition target="../running" event="continue" port="input">
                     <raise event="time_update" port="output">
                         <parameter expr="self.getSimulatedTime()" />
-                        <parameter expr="time()" />
+                        <parameter expr="self.getWallClockTime()" />
                     </raise>
                 </transition>
             </state>

+ 15 - 14
src/python_sccd/python_sccd_runtime/accurate_time.py

@@ -1,17 +1,18 @@
 import time as t
 import os
 
-global start_time
-def set_start_time():
-    global start_time
-    if os.name == 'posix':
-        start_time = t.time()
-    elif os.name == 'nt':
-        start_time = t.clock()
-
-if os.name == 'posix':
-    def time():
-        return int((t.time() - start_time) * 1000)
-elif os.name == 'nt':
-    def time():
-        return int((t.clock() - start_time) * 1000)
+class AccurateTime:
+    def __init__(self):
+        if os.name == 'posix':
+            self._get_wct_time = lambda self: int((t.time() - self.start_time) * 1000)
+        elif os.name == 'nt':
+            self._get_wct_time = lambda self: int((t.clock() - self.start_time) * 1000)
+        
+    def set_start_time(self):
+        if os.name == 'posix':
+            self.start_time = t.time()
+        elif os.name == 'nt':
+            self.start_time = t.clock()
+            
+    def get_wct(self):
+        return self._get_wct_time(self)

+ 17 - 8
src/python_sccd/python_sccd_runtime/statecharts_core.py

@@ -12,7 +12,7 @@ from infinity import INFINITY
 from Queue import Queue, Empty 
 
 from sccd.runtime.event_queue import EventQueue
-import sccd.runtime.accurate_time as accurate_time
+from sccd.runtime.accurate_time import AccurateTime
 
 DEBUG = False
 
@@ -433,8 +433,14 @@ class ControllerBase(object):
         self.simulated_time = None
         self.behind = False
         
+        # accurate timer
+        self.accurate_time = AccurateTime()
+        
     def getSimulatedTime(self):
         return self.simulated_time
+        
+    def getWallClockTime(self):
+        return self.accurate_time.get_wct()
             
     def addInputPort(self, virtual_name, instance = None):
         if instance == None:
@@ -452,7 +458,7 @@ class ControllerBase(object):
         self.object_manager.broadcast(new_event, time_offset)
         
     def start(self):
-        accurate_time.set_start_time()
+        self.accurate_time.set_start_time()
         self.simulated_time = 0
         self.object_manager.start()
     
@@ -474,7 +480,7 @@ class ControllerBase(object):
             if force_internal:
                 self.input_queue.add((0 if self.simulated_time is None else self.simulated_time) + time_offset, e)
             else:
-                self.input_queue.add((0 if self.simulated_time is None else accurate_time.time()) + time_offset, e)
+                self.input_queue.add((0 if self.simulated_time is None else self.accurate_time.get_wct()) + time_offset, e)
 
     def getEarliestEventTime(self):
         return min(self.object_manager.getEarliestEventTime(), self.input_queue.getEarliestTime())
@@ -574,7 +580,7 @@ class EventLoopControllerBase(ControllerBase):
         ControllerBase.stop(self)
 
     def run(self):
-        start_time = accurate_time.time()
+        start_time = self.accurate_time.get_wct()
         try:
             self.running = True
             while 1:
@@ -588,7 +594,7 @@ class EventLoopControllerBase(ControllerBase):
                 if earliest_event_time == INFINITY:
                     if self.finished_callback: self.finished_callback() # TODO: This is not necessarily correct (keep_running necessary?)
                     return
-                now = accurate_time.time()
+                now = self.accurate_time.get_wct()
                 if now - start_time > 10 or earliest_event_time - now > 0:
                     self.event_loop.schedule(self.run, earliest_event_time - now, now - start_time > 10)
                     if now - earliest_event_time > 10 and now - self.last_print_time >= 1000:
@@ -642,7 +648,7 @@ class ThreadsControllerBase(ControllerBase):
             earliest_event_time = self.getEarliestEventTime()
             if earliest_event_time == INFINITY and not self.keep_running:
                 return
-            now = accurate_time.time()
+            now = self.accurate_time.get_wct()
             if earliest_event_time - now > 0:
                 if self.behind:                
                     print '\r' + ' ' * 80,
@@ -954,10 +960,13 @@ class RuntimeClassBase(object):
         self.__set_stable(True)
         
     def sccd_yield(self):
-        return max(0, (accurate_time.time() - self.controller.simulated_time) / 1000.0)
+        return max(0, (self.accurate_time.get_wct() - self.controller.simulated_time) / 1000.0)
         
     def getSimulatedTime(self):
-        return self.controller.simulated_time
+        return self.controller.getSimulatedTime()
+        
+    def getWallClockTime(self):
+        return self.controller.getWallClockTime()
     
     def updateConfiguration(self, states):
         self.configuration.extend(states)

+ 0 - 1
src/python_sccd/python_sccd_runtime/tkinter_eventloop.py

@@ -1,5 +1,4 @@
 from sccd.runtime.statecharts_core import EventLoop
-from sccd.runtime.accurate_time import time
 
 import math