#define true 1
#define false 0

chan swapin = [1] of {int};
chan swapout = [1] of {int};

bool ain,bin;

int mayi;

inline swap(in,out,k){
  in!k;
  out?k;
}

proctype givechance(){
  if
    :: mayi>2->mayi=0;
    :: else->mayi=mayi+1
  fi
}

proctype A()
{
   int key;

   key = true;
   do
    :: key ->
accept: run givechance();mayi==1; 
       swap(swapin, swapout, key);
    :: !key -> break;
   od;
progress:
   ain=true;
   assert(bin==false);
   ain=false;
   (mayi == 1);
   run givechance();mayi==1;
   swap(swapin, swapout, key);
}

proctype B()
{
   int key;

   key = true;
   do
    :: key ->
accept: run givechance();mayi==2;
       swap(swapin,swapout,key);
       !key -> break;
   od;
progress:

   bin=true;
   assert(ain==false);
   bin=false;
   run givechance();mayi==2;
   swap(swapin,swapout,key);
}

inline klswap(k,l){
  int tmp;
  tmp = k;
  k = l;
  l = tmp;
}

proctype swapproc(){
int key,lock;
bit i;
   
   lock = false;
end:
   do
     :: swapin ? key->
         klswap(key,lock);
         swapout ! key;
   od;
}  

init
{
  atomic{
    run A(); 
    run B();
    run swapproc();
    run givechance();
  }
}

