Consider again the producer/consumer example with two producers and two consumers, from a previous lesson:
event int provide; automaton producer1: disc int nr = 0; location: initial; edge provide!nr do nr := nr + 1; end automaton producer2: disc int nr = 0; location: initial; edge provide!nr do nr := nr + 1; end automaton consumer1: disc list int nrs; location: initial; edge provide? do nrs := nrs + [?]; end automaton consumer2: disc list int nrs; location: initial; edge provide? do nrs := nrs + [?]; end
Now assume we want to restrict communication to allow at most five products in total to be provided to the consumers. We could adapt both producers, as follows:
automaton producer1: disc int nr = 0; location: initial; edge provide!nr when nr + producer2.nr < 5 do nr := nr + 1; end automaton producer2: disc int nr = 0; location: initial; edge provide!nr when producer1.nr + nr < 5 do nr := nr + 1; end
Each producer gets an additional guard condition whether it may provide a product to one of the consumers. If the total number of products provided by both providers does not exceed five, they may still provide a product. Having to adapt both producers is less than ideal.
As an alternative solution, we can add an additional automaton, instead of adapting the producers:
automaton controller: disc int cnt = 0; location: initial; edge provide when cnt < 5 do cnt := cnt + 1; end
controller automaton (together with the original producer automata) keeps track of the number of products provided to consumers, by counting them in variable
cnt. It only allows the
provide event when less than five products have been provided. If five or more products have been provided, it disables the
controller automaton, the
provide channel is used as an event rather than a channel. When one of the producers and one of the consumers together perform a channel communication, the
controller automaton that has the
provide event in its alphabet, must synchronize with it. This allows the
controller to impose additional restrictions on the channel communication, allowing or forbidding it in certain cases. The
controller is added as a separate process, which improves scalability.
In general, every automaton may either send over a channel, receive over a channel, or synchronize with a channel. An automaton may not take on more than one of these roles, for a single event. It may however send over one channel, receive over another channel, and synchronize with yet another one.
Every event transition for a channel requires exactly one automaton that participates as sender, and exactly one automaton that participates as receiver. Furthermore, all automata that have the channel in their alphabet, must additionally participate as well, by synchronizing together with the sender and receiver. Automata that send or receive over a channel, do not have that channel in their alphabet. Only automata that synchronize with an event or channel have that event or channel in their alphabet.
Automata that synchronize over a channel can be used to further restrict the allowed channel communications, as shown in the above example. It is however also possible for the additional synchronizing automata to monitor (observe) the channel communication.