Evaluating event listeners for all A-events followed by all B-events
Consider the following event listener definition:
on all A() -> all B() success();
or
on ( ( all A() ) -> ( all B() ) ) success();
Now the monitor would match on an A and create another event listener to look for further As. Each of these event listeners will go on to search for a B after it encounters an A. However, in this instance all event listeners are duplicated once more after matching against a B.
The effect of this would be that on all A -> all B would match {A1, B1}, {A1, B2}, {A1, B3}, {A2, B1}, {A2, B2}, {A2, B3} and {A3, B3}. That is, all the possible permutations. This could cause a very large number of sub-event-listeners to be created.
Note: | The all operator must be used with caution as it can create a very large number of sub-event-listeners, all looking for concurrent patterns. This is particularly applicable if multiple all operators are nested within each other. This can have an adverse impact on performance. |
Now consider the example,
on all ( A() -> all B() ) success();
This will match the first A followed by all subsequent Bs. However, as on every match of an A followed by B, ( A() -> all B() ) becomes true, then a new search for the "next" A followed by all subsequent Bs will start. This will repeat itself recursively, and eventually there could be several concurrent sub-event-listeners that might match on the same patterns, thus causing duplicate triggering.
Give the same event pattern as described in
Evaluating event listeners for all A-events followed by
B-events, this would be evaluated as follows:
Thus matching against {A1, B1}, {A1, B2}, {A1, B3}, and twice against {A3, B3}. Notice how the number of active event listeners is progressively increasing, until after t12 there would actually be six active event listeners, three looking for a B and three looking for an A.