소스 검색

Fixed use of afters

Yentl Van Tendeloo 8 년 전
부모
커밋
06862ecc10
2개의 변경된 파일62개의 추가작업 그리고 33개의 파일을 삭제
  1. 13 0
      integration/code/minimal_SCCD.mvc
  2. 49 33
      models/SCCD_execute.alc

+ 13 - 0
integration/code/minimal_SCCD.mvc

@@ -46,6 +46,10 @@ CompositeState main_statechart {
                 name = "xc"
                 isInitial = False
             }
+            {composite_children} BasicState x_d {
+                name = "xd"
+                isInitial = False
+            }
         }
 
         {parallel_children} CompositeState parallel_y {
@@ -73,6 +77,15 @@ transition (x_a, x_b) {
         $
 }
 
+transition (x_a, x_d) {
+    name = "timeout"
+    after = $
+            Float function after(attributes : Element):
+                log("In after")
+                return 3.0!
+        $
+}
+
 transition (x_b, x_c) {
     name = "Z"
     cond = $

+ 49 - 33
models/SCCD_execute.alc

@@ -135,19 +135,35 @@ Element function get_enabled_transitions(model : Element, state : String, data :
 
 	while (read_nr_out(to_filter) > 0):
 		transition = set_pop(to_filter)
+
+		// Check event
 		attr = read_attribute(model, transition, "event")
-		if (bool_or(element_eq(attr, read_root()), set_in(data["events"], attr))):
-			// Event is OK
-			cond = read_attribute(model, transition, "cond")
-			if (element_neq(cond, read_root())):
-				cond = get_func_AL_model(import_node(cond))
-				// Execute condition
-				if (bool_not(cond(data["classes"][class]["attributes"]))):
-					// Condition false, so skip
+		if (bool_not(bool_or(element_eq(attr, read_root()), set_in(data["events"], attr)))):
+			continue!
+
+		// Check after
+		// Only an after if there was no event!
+		if (bool_and(element_eq(attr, read_root()), read_attribute(model, transition, "after"))):
+			if (dict_in(data["classes"][class]["timers"], transition)):
+				// Registered timer already, let's check if it has expired
+				if (float_gt(data["classes"][class]["timers"][transition], time())):
+					// Not enabled yet
 					continue!
-
-			// Condition is OK
-			set_add(result, transition)
+			else:
+				// Not registered even, so not enabled either
+				continue!
+
+		// Check condition
+		cond = read_attribute(model, transition, "cond")
+		if (element_neq(cond, read_root())):
+			cond = get_func_AL_model(import_node(cond))
+			// Execute condition
+			if (bool_not(cond(data["classes"][class]["attributes"]))):
+				// Condition false, so skip
+				continue!
+
+		// All is OK for this transition
+		set_add(result, transition)
 
 	return result!
 
@@ -218,39 +234,39 @@ Void function reschedule_timeouts(model : Element, data : Element, class : Strin
 	String state
 
 	timed_transitions = create_node()
-	states = dict_keys(data["classes"][class]["states"])
+	states = set_copy(data["classes"][class]["states"])
+
+	// Collect all timed transitions that are currently active
 	while (read_nr_out(states) > 0):
 		state = set_pop(states)
 
 		// NOTE this set_merge does not eliminate duplicates, though this should happen later on when adding the timer (see other NOTE)
 		timed_transitions = set_merge(timed_transitions, filter_exists(model, allOutgoingAssociationInstances(model, state, "SCCD/transition"), "after"))
 
-		// Remove timers that no longer exist
-		old_timed_transitions = dict_keys(data["classes"][class]["timers"])
-		while (read_nr_out(old_timed_transitions) > 0):
-			transition = set_pop(old_timed_transitions)
-
-			if (bool_not(set_in(timed_transitions, transition))):
-				// Transition is no longer scheduled for any state, so remove
-				dict_delete(data["classes"][class]["timers"], transition)
+	// Remove timers that no longer exist
+	old_timed_transitions = dict_keys(data["classes"][class]["timers"])
+	while (read_nr_out(old_timed_transitions) > 0):
+		transition = set_pop(old_timed_transitions)
 
-		// Schedule timers that are not already scheduled
-		while (read_nr_out(timed_transitions) > 0):
-			transition = set_pop(timed_transitions)
+		if (bool_not(set_in(timed_transitions, transition))):
+			// Transition is no longer scheduled for any state, so remove
+			dict_delete(data["classes"][class]["timers"], transition)
 
-			// NOTE Normally, a timer will not be added twice here, as the previous occurence will already find it
-			if (bool_not(dict_in(data["classes"][class]["timers"], transition))):
-				// Not yet scheduled this transition: do so now
-				Element after
-				Float after_duration
+	// Schedule timers that are not already scheduled
+	while (read_nr_out(timed_transitions) > 0):
+		transition = set_pop(timed_transitions)
 
-				after = read_attribute(model, transition, "after")
-				after = get_func_AL_model(import_node(after))
-				after_duration = after(data["classes"][class]["attributes"])
+		// NOTE Normally, a timer will not be added twice here, as the previous occurence will already find it
+		if (bool_not(dict_in(data["classes"][class]["timers"], transition))):
+			// Not yet scheduled this transition: do so now
+			Element after
+			Float after_duration
 
-				log("Schedule transition after " + cast_v2s(after_duration))
+			after = read_attribute(model, transition, "after")
+			after = get_func_AL_model(import_node(after))
+			after_duration = after(data["classes"][class]["attributes"])
 
-				dict_add(data["classes"][class]["timers"], transition, float_addition(data["start_time"], after_duration))
+			dict_add(data["classes"][class]["timers"], transition, float_addition(data["start_time"], after_duration))
 
 	return !