如何在Spin中检查消息队列中的任意条件?

时间:2019-04-09 15:25:02

标签: model-checking promela spin

我正在尝试使用Spin模拟其他模型检查器的行为。为此,我需要能够测试消息队列中的任意条件。例如,我想检查通道中某处是否存在一些int大于5的消息。不仅如此,我还需要在原子块中放置这样的条件。

我试图做这样的事情:

int mid;

do
:: atomic {
  in??[msg(mid)] && mid > 5 -> (...)
}

但是Spin将该条件读取为

in??[msg(mid)] && 0 > 5

我已经尝试过这样的事情:

do
:: atomic {
    in??<msg(mid)>;
    if
    :: mid > 5 ->
        in??msg(eval(mid));
        (...)
    :: else -> skip
    fi }

这是可行的,但是在语义上与我想要的有所不同,因为它进入原子块只是为了使该条件失败并跳过它。

那么,是否有某种方法可以检查消息队列中的任意条件,并且仅在这种条件有效的情况下才执行原子块?

1 个答案:

答案 0 :(得分:1)

如您所见,Spin提供的本机过滤机制只能按值过滤,更具体地说,它不能按表达式过滤 >。

这可能看起来不是理想的解决方案,但是最简单的方法是在发送消息之前评估与过滤条件关联的布尔表达式。

示例:

chan c = [42] of { int, bool };

proctype Test()
{
    int value;
    do
        :: atomic {
            c??[value, true] ->
                c??value, true; // true: filter messages larger than 5
                printf("Popped: %d\n", value);
            }
        :: else ->
            printf("No more messages larger than 5.\n");
            break;
    od;

    bool cond;
    printf("\nDischarging Channel..\n");
    do
        :: c?[value, cond] ->
           c?value, cond;
           printf("Popped: %d\n", value);
        :: else ->
            break;
    od;
}

init {
    int i;
    for (i : 1 .. 10) {
        c!i(i >= 5)  // evaluate filtering condition when message is sent
    }

    run Test();
}

输出:

~$ spin test.pml 
          Popped: 5
          Popped: 6
          Popped: 7
          Popped: 8
          Popped: 9
          Popped: 10
          No more messages larger than 5.

Discharging Channel..
          Popped: 1
          Popped: 2
          Popped: 3
          Popped: 4
2 processes created

我承认这并不是真正的可扩展方法,但是我无法提出其他解决方案