逻辑评估“何时A和B ...”

时间:2019-10-24 11:57:48

标签: model-checking promela spin

给出一条语句“当CM空闲并从WCP接收更新请求时,它将设置...。” 某些上下文:通道中只能存在一种类型的味精,即仅包含来自wcp的更新请求。

我可以想到2种可能的实现。但是,我不太确定哪种方法正确。

第一种方式:

    do
    :: CM_STATUS == IDLE && nempty(wcpOut) -> // remove msg from channel and set something;
    od;

第二种方式

    mtype receivedMessage;
    do
    :: CM_STATUS == IDLE -> 
        if
        :: wcpOut?receivedMessage -> // set something;
        fi;
    od;

1 个答案:

答案 0 :(得分:1)

两个例子完全不同。

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中控制器的行为。 (例如,您将获得"dubious use of 'else' combined with i/o" error message if you tried to add an else branch)。

恕我直言,更好的选择是

do
    :: atomic{ nempty(my_channel) -> my_channel?receiveMessage; } ->
        ...
    :: empty(my_channel) -> // do something else

od;

相反,当您想使用message filtering时,可以使用message polling

do
    :: atomic{ my_channel?[MESSAGE_TYPE] -> my_channel?MESSAGE_TYPE } ->
        ...
    :: else -> // do something else
od;

您是否选择将这些条件与CM_STATUS == IDLE一起使用还是您更愿意使用嵌套方法完全取决于您,除非您有理由相信CM_STATUS变量可以被其他过程改变了。可以提高可读性时,我几乎总是使用第二种样式。