瀏覽代碼

broadcast events are no longer sent to sending instance

Simon Van Mierlo 7 年之前
父節點
當前提交
74d29762ec

+ 1 - 1
examples/bouncingballs/python/bouncing.xml

@@ -206,7 +206,7 @@
                 </transition>
                 </transition>
             </parallel>
             </parallel>
             <state id="stopped">
             <state id="stopped">
-                <onentry>                
+                <onentry>
                     <raise event="delete_window" scope="narrow" target="'parent'">
                     <raise event="delete_window" scope="narrow" target="'parent'">
                         <parameter expr="self.association_name" />
                         <parameter expr="self.association_name" />
                     </raise>
                     </raise>

+ 14 - 0
examples/my-tests/python/SCCD_broadcast/runner.py

@@ -0,0 +1,14 @@
+import sys
+sys.path.append("../")
+
+import tester
+import threading
+from sccd.runtime.statecharts_core import Event
+import time
+
+controller = tester.Controller(keep_running=False)
+
+try:
+    controller.start()
+except KeyboardInterrupt:
+    pass

+ 107 - 0
examples/my-tests/python/SCCD_broadcast/tester.py

@@ -0,0 +1,107 @@
+"""
+Generated by Statechart compiler by Glenn De Jonghe, Joeri Exelmans, Simon Van Mierlo, and Yentl Van Tendeloo (for the inspiration)
+
+Date:   Thu Sep 07 09:33:21 2017
+
+Model author: Yentl Van Tendeloo
+Model name:   Testing
+Model description:
+Testing
+"""
+
+from sccd.runtime.statecharts_core import *
+
+# package "Testing"
+
+class Testing(RuntimeClassBase):
+    def __init__(self, controller):
+        RuntimeClassBase.__init__(self, controller)
+        
+        self.semantics.big_step_maximality = StatechartSemantics.TakeMany
+        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
+        Testing.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 /A
+        self.states["/A"] = ParallelState(1, "/A", self)
+        
+        # state /A/B
+        self.states["/A/B"] = State(2, "/A/B", self)
+        
+        # state /A/B/C
+        self.states["/A/B/C"] = State(3, "/A/B/C", self)
+        self.states["/A/B/C"].setEnter(self._A_B_C_enter)
+        
+        # state /A/D
+        self.states["/A/D"] = State(4, "/A/D", self)
+        
+        # state /A/D/E
+        self.states["/A/D/E"] = State(5, "/A/D/E", self)
+        
+        # add children
+        self.states[""].addChild(self.states["/A"])
+        self.states["/A"].addChild(self.states["/A/B"])
+        self.states["/A"].addChild(self.states["/A/D"])
+        self.states["/A/B"].addChild(self.states["/A/B/C"])
+        self.states["/A/D"].addChild(self.states["/A/D/E"])
+        self.states[""].fixTree()
+        self.states[""].default_state = self.states["/A"]
+        self.states["/A/B"].default_state = self.states["/A/B/C"]
+        self.states["/A/D"].default_state = self.states["/A/D/E"]
+        
+        # transition /A/D/E
+        _A_D_E_0 = Transition(self, self.states["/A/D/E"], [self.states["/A/D/E"]])
+        _A_D_E_0.setAction(self._A_D_E_0_exec)
+        _A_D_E_0.setTrigger(Event("Z", None))
+        self.states["/A/D/E"].addTransition(_A_D_E_0)
+    
+    def _A_B_C_enter(self):
+        self.raiseInternalEvent(Event("Z", None, []))
+    
+    def _A_D_E_0_exec(self, parameters):
+        self.big_step.outputEventOM(Event("broad_cast", None, [self, Event("Z", None, [])]))
+        print("Transition fired!")
+    
+    def initializeStatechart(self):
+        # enter default state
+        self.default_targets = self.states["/A"].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 == "Testing":
+            instance = Testing(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("Testing", [])

+ 31 - 0
examples/my-tests/python/SCCD_broadcast/tester.xml

@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<diagram author="Yentl Van Tendeloo" name="Testing">
+    <description>
+        Testing
+    </description>
+
+    <class name="Testing" default="true">
+        <scxml initial="A">
+            <parallel id="A">
+                <state id="B">
+                    <state id="C">
+                        <onentry>
+                            <raise event="Z"/>
+                        </onentry>
+                    </state>
+                </state>
+
+                <state id="D">
+                    <state id="E">
+                        <transition event="Z" target=".">
+                            <raise event="Z" scope="broad"/>
+                            <script>
+                                print("Transition fired!")
+                            </script>
+                        </transition>
+                    </state>
+                </state>
+            </parallel>
+        </scxml>
+    </class>
+</diagram>

+ 5 - 5
src/javascript_sccd_runtime/statecharts_core.js

@@ -147,10 +147,10 @@ ObjectManagerBase.prototype.addEvent = function(the_event, time_offset) {
 	this.events.add(new EventQueueEntry(this.controller.simulated_time + time_offset, the_event));
 	this.events.add(new EventQueueEntry(this.controller.simulated_time + time_offset, the_event));
 };
 };
 
 
-ObjectManagerBase.prototype.broadcast = function(new_event, time_offset) {
+ObjectManagerBase.prototype.broadcast = function(source, new_event, time_offset) {
 	if (time_offset === undefined) time_offset = 0;
 	if (time_offset === undefined) time_offset = 0;
 	for (var i in this.instances) {
 	for (var i in this.instances) {
-		if (!this.instances.hasOwnProperty(i)) continue;
+		if (!this.instances.hasOwnProperty(i) || i == source) continue;
 		this.instances[i].addEvent(new_event, time_offset);
 		this.instances[i].addEvent(new_event, time_offset);
 	}
 	}
 };
 };
@@ -246,10 +246,10 @@ ObjectManagerBase.prototype.handleStartInstanceEvent = function(parameters) {
 };
 };
 
 
 ObjectManagerBase.prototype.handleBroadcastEvent = function(parameters) {
 ObjectManagerBase.prototype.handleBroadcastEvent = function(parameters) {
-	if (parameters.length !== 1) {
-		throw new ParameterException("The broadcast event needs 1 parameter.");
+	if (parameters.length !== 2) {
+		throw new ParameterException("The broadcast event needs 2 parameters (source of event and event name).");
 	}
 	}
-	this.broadcast(parameters[0]);
+	this.broadcast(parameters[0], parameters[1]);
 };
 };
 
 
 ObjectManagerBase.prototype.handleCreateEvent = function(parameters) {
 ObjectManagerBase.prototype.handleCreateEvent = function(parameters) {

+ 1 - 0
src/python_sccd/python_sccd_compiler/generic_generator.py

@@ -838,6 +838,7 @@ class GenericGenerator(Visitor):
                     GLC.String("broad_cast"),
                     GLC.String("broad_cast"),
                     GLC.NoneExpression(),
                     GLC.NoneExpression(),
                     GLC.ArrayExpression([
                     GLC.ArrayExpression([
+                        GLC.SelfExpression(),
                         new_event_expr])])]))
                         new_event_expr])])]))
             
             
     def visit_Script(self, script):
     def visit_Script(self, script):

+ 6 - 5
src/python_sccd/python_sccd_runtime/statecharts_core.py

@@ -129,9 +129,10 @@ class ObjectManagerBase(object):
         self.events.add(self.controller.simulated_time + time_offset, event)
         self.events.add(self.controller.simulated_time + time_offset, event)
         
         
     # broadcast an event to all instances
     # broadcast an event to all instances
-    def broadcast(self, new_event, time_offset = 0):
+    def broadcast(self, source, new_event, time_offset = 0):
         for i in self.instances:
         for i in self.instances:
-            i.addEvent(new_event, time_offset)
+            if i != source:
+                i.addEvent(new_event, time_offset)
         
         
     def getEarliestEventTime(self):
     def getEarliestEventTime(self):
         while self.instance_times and self.instance_times[0][0] < self.instance_times[0][1].earliest_event_time:
         while self.instance_times and self.instance_times[0][0] < self.instance_times[0][1].earliest_event_time:
@@ -198,9 +199,9 @@ class ObjectManagerBase(object):
             source.addEvent(Event("instance_started", parameters = [parameters[1]]))
             source.addEvent(Event("instance_started", parameters = [parameters[1]]))
         
         
     def handleBroadCastEvent(self, parameters):
     def handleBroadCastEvent(self, parameters):
-        if len(parameters) != 1:
-            raise ParameterException ("The broadcast event needs 1 parameter.")
-        self.broadcast(parameters[0])
+        if len(parameters) != 2:
+            raise ParameterException ("The broadcast event needs 2 parameters (source of event and event name).")
+        self.broadcast(parameters[0], parameters[1])
 
 
     def handleCreateEvent(self, parameters):
     def handleCreateEvent(self, parameters):
         if len(parameters) < 2:
         if len(parameters) < 2: