wiki:Choose

$choose statement

current syntax

$choose{
  S1
  S2
  ...
  default: Sn
}

Sk (k=1..n) could be any statement: a compound statement, any kind of atomic statement, a guarded statement, any other statement (if-else, while, for, ...).

example

$choose{
  $when(x<0){$when(y>0){int k; k=x+y;}}
  $when(1){ 
    $comm_enqueue(comm, out);
    in = $comm_dequeue(comm, source, recvtag);
  }
  $when(1){
    in = $comm_dequeue(comm, source, recvtag);
    $comm_enqueue(comm, out);
  }
}

the result of the current translation would be

TRANS1:

LOC0:
[x<0 && y>0] k=x+y -> LOC3
[true] $comm_enqueue(...) -> LOC1
[comm_probe()] $comm_dequeue(...) -> LOC2

LOC1:
[$comm_probe()] $comm_dequeue(...) -> LOC3

LOC2:
[true] $comm_enqueue(...) -> LOC3

LOC3:
...  

problem of current translation (TRANS1)

  1. when there are new scope introduced by the any clause, the clauses can't share the same source location in the model, because a location is associated with a unique scope; for example, at LOC0 in TRANS1, the first statement accesses k but k isn't visible in the scope associated to LOC0 (LOC0 is corresponding to the scope at $choose)
  2. a quick solution for 1 is introduce a noop at the beginning of each clause, and move the guard of the first statement of the clause to the noop; this would translate the example into TRANS2:

TRANS2:

LOC0:
[x<0 && y>0] noop -> LOC1
[true] noop -> LOC2
[comm_probe()] noop  -> LOC3

LOC1:
[true] k=x+y; -> LOC

LOC2:
[true] $comm_enqueue(...) -> LOC4

LOC3:
[true] $comm_dequeue(...) -> LOC5

LOC4:
[$comm_probe()] $comm_dequeue(...) -> LOC6

LOC5:
[true] $comm_enqueue(...) -> LOC6

LOC6:
...  

problem of TRANS2

There are still a few problems in the above translation (TRANS2):

  1. it breaks the checking of potential deadlock. CIVL will report a false alarm of a potential deadlock.
  2. the extra noop changes the semantics slightly: for example, if at LOC0, the first noop is chosen to executed, i.e., x<0 && y>0 is evaluated to be true; and then another process updates the value of x or y and then x<0 && y>0 is no longer true, but since the process is now at LOC1, so the statement k=x+y will still be executed. This conflicts with the semantics of the guarded statement $when(x<0){$when(y>0){int k; k=x+y;}}.

new solutions

new syntax

  • requires curly braces in each clause of $choose , not allowing clauses to introduce new scopes
    choose_stmt: ‘$choose’ ‘{‘  choose_clause+ ‘}’;
    
    choose_clause: 
          ‘{‘ block_item* ‘}’      
        | when_stmt   
        | labeled_stmt 
    
  • uses labels
    $choose {
    
      LABEL0:  stmt*;
    
      LABEL1:  stmt*;
    
    
    }
    

translation notes

  • inside a compound statement that is the body of a $when/$atomic/$atom or a clause in a $choose, if the first item is a declaration a no-op is inserted before it in translation. Then you are guaranteed that the guard will never involve a new variable.

example:

$when (e) {int x; blah}  translated to:   
    LOC0 -e:noop-> LOC1(int x)
$when (e) {$when (f) S} translated to: (let So the first atomic statement in S)
    LOC0 -e&&f:S0-> LOC1  if S0 is not a variable declaration
or otherwise
    LOC0 -e&&f:noop-> LOC1(variable declared by S0) 
$when (e) {$comm_dequeue; …} translated to: 
    LOC0 -e&&$comm_probe(…):$comm_dequeue()-> LOC1
Last modified 11 years ago Last modified on 09/16/15 12:03:23
Note: See TracWiki for help on using the wiki.