Browse Source

Prepare for multi-event triggers: Event trigger has bitmap with event_id's required to enable the transition.
Optimization: Store bitmap with single bit at position 'state_id' set instead of calculating it each time.

Joeri Exelmans 5 years ago
parent
commit
836c690e01
3 changed files with 12 additions and 15 deletions
  1. 5 13
      src/sccd/execution/round.py
  2. 2 2
      src/sccd/execution/statechart_state.py
  3. 5 0
      src/sccd/syntax/tree.py

+ 5 - 13
src/sccd/execution/round.py

@@ -11,7 +11,7 @@ class CandidatesGenerator:
 
 class CandidatesGeneratorCurrentConfigBased(CandidatesGenerator):
     def generate(self, state, enabled_events: List[Event], arenas_changed: Bitmap) -> Iterable[Transition]:
-        # events_bitmap = Bitmap.from_list(e.id for e in enabled_events)
+        events_bitmap = Bitmap.from_list(e.id for e in enabled_events)
         key = (state.configuration_bitmap, arenas_changed)
 
         try:
@@ -19,22 +19,14 @@ class CandidatesGeneratorCurrentConfigBased(CandidatesGenerator):
         except KeyError:
             candidates = self.cache[key] = [
                 t for s in state.configuration
-                    if (not arenas_changed.has(s.gen.state_id))
+                    if (not arenas_changed & s.gen.state_id_bitmap)
                     for t in s.transitions
                 ]
             if self.reverse:
                 candidates.reverse()
 
-        def check_trigger(t, enabled_events):
-            if not t.trigger:
-                return True
-            for e in enabled_events:
-                if t.trigger.id == e.id:
-                    return True
-            return False
-
         def filter_f(t):
-            return check_trigger(t, enabled_events) and state.check_guard(t, enabled_events)
+            return (not t.trigger or t.trigger.check(events_bitmap)) and state.check_guard(t, enabled_events)
         return filter(filter_f, candidates)
 
 class CandidatesGeneratorEventBased(CandidatesGenerator):
@@ -47,8 +39,8 @@ class CandidatesGeneratorEventBased(CandidatesGenerator):
         except KeyError:
             candidates = self.cache[key] = [
                 t for t in state.model.tree.transition_list
-                    if (not t.trigger or events_bitmap.has(t.trigger.id)) # todo: check port?
-                    and (not arenas_changed.has(t.source.gen.state_id))
+                    if (not t.trigger or t.trigger.check(events_bitmap)) # todo: check port?
+                    and (not arenas_changed & t.source.gen.state_id_bitmap)
                 ]
             if self.reverse:
                 candidates.reverse()

+ 2 - 2
src/sccd/execution/statechart_state.py

@@ -109,7 +109,7 @@ class StatechartState:
     try:
         self.configuration = self.config_mem[self.configuration_bitmap]
     except KeyError:
-        self.configuration = self.config_mem[self.configuration_bitmap] = [s for s in self.model.tree.state_list if self.configuration_bitmap.has(s.gen.state_id)]
+        self.configuration = self.config_mem[self.configuration_bitmap] = [s for s in self.model.tree.state_list if self.configuration_bitmap & s.gen.state_id_bitmap]
 
     return t.gen.arena_bitmap
 
@@ -128,7 +128,7 @@ class StatechartState:
           return result
 
   def check_source(self, t) -> bool:
-      return self.configuration_bitmap.has(t.source.gen.state_id)
+      return self.configuration_bitmap & t.source.gen.state_id_bitmap
 
   def _perform_actions(self, events, actions: List[Action]):
       for a in actions:

+ 5 - 0
src/sccd/syntax/tree.py

@@ -36,6 +36,7 @@ class State:
 @dataclass(frozen=True)
 class StateOptimization:
     state_id: int
+    state_id_bitmap: Bitmap
     full_name: str
     ancestors: List[State] # order: close to far away, i.e. first element is parent
     descendants: List[State]  # order: breadth-first
@@ -91,6 +92,9 @@ class EventTrigger:
     def __post_init__(self):
         self.bitmap = bit(self.id)
 
+    def check(self, events_bitmap: Bitmap) -> bool:
+        return (self.bitmap & events_bitmap) == self.bitmap
+
     def render(self) -> str:
         if self.port:
             return self.port+'.'+self.name
@@ -181,6 +185,7 @@ class StateTree:
 
             state.gen = StateOptimization(
                 state_id=state_id,
+                state_id_bitmap=bit(state_id),
                 full_name=full_name,
                 ancestors=ancestors,
                 descendants=descendants,