1

I'm trying to simulate the behaviour of other model-checkers using Spin. For that, I need to be able to test for some arbitrary condition in the message queue. For instance, I want to check if somewhere in the channel there exists some message with an int greater than 5. Not only that, I need such condition to be inside an atomic block.

I tried doing something like this:

int mid;

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

But Spin reads that condition as

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

I've tried something of this sort:

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

Which works, but is semantically different from what I want because it gets into the atomic block only for it to fail that condition and skip it.

So, is there some way of checking for an arbitrary condition in a message queue and to only execute an atomic block if such condition is valid?

1 Answers1

1

As you discovered, the native filtering mechanism offered by Spin is only able to filter by value and, more specifically, it is unable to filter by expression.

This may not look like an ideal solution, but the simplest approach is to evaluate the Boolean expression associated with the filtering condition before the message is sent.

Example:

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();
}

Output:

~$ 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

I admit that this is not really a scalable approach, but I could not come up with any other solution.

Patrick Trentin
  • 7,126
  • 3
  • 23
  • 40