Два примера немного отличаются.
do
:: CM_STATUS == IDLE && nempty(wcpOut) -> // read msg
od;
Здесь вы обязуетесь прочитать сообщение, если ваше состояние idle
и канал wcpOut
не пуст. Однако что произойдет, если процесс будет прерван прямо после оценки nempty(wcpOut)
, и сообщение будет прочитано кем-то другим? В этом случае процесс может оказаться заблокированным.
mtype receivedMessage;
do
:: CM_STATUS == IDLE ->
if
:: wcpOut?receivedMessage -> // set something;
fi;
od;
Здесь вы обязуетесь прочитать сообщение, когда состояние idle
, поэтому вы не можете реагировать на изменение состояния вплоть до того момента, когдасообщение читается.
Я бы не использовал ни один из подходов, за исключением простых примеров .
Недостаток первого метода заключается в том, что он не выполняетдве операции атомарно. Недостаток второго метода состоит в том, что он затрудняет расширение поведения вашего контроллера в режиме ожидания state
, добавляя дополнительные условия. (Например, вы получите сообщение об ошибке «сомнительное использование else» в сочетании с вводом-выводом », если попытаетесь добавить else
branch ).
ИМХО , лучшим вариантом будет
do
:: atomic{ nempty(my_channel) -> my_channel?receiveMessage; } ->
...
:: empty(my_channel) -> // do something else
od;
Вместо этого, когда вы хотите использовать фильтрацию сообщений , вы можете использовать опрос сообщений :
do
:: atomic{ my_channel?[MESSAGE_TYPE] -> my_channel?MESSAGE_TYPE } ->
...
:: else -> // do something else
od;
Если вы решите присоединиться к этим условиям с помощью CM_STATUS == IDLE
или предпочитаете использовать вложенный подход,полностью на ваше усмотрение, если у вас нет оснований полагать, что переменная CM_STATUS
может быть изменена каким-либо другим процессом. Я почти всегда использовал бы второй стиль, когда он может улучшить читаемость.