A few examples are also available, readwrite counters, concurrent queues, and a toy webserver.
import java.util.concurrent.*;
import java.util.concurrent.locks.*;
import java.util.concurrent.locks.ReentrantReadWriteLock.*;
/*@
predicate_ctor CCounter_shared_state (RWCounter c) () =
c.N |-> ?v &*& v >= 0 &*& c.MAX |-> ?m &*& m > 0 &*& v <= m;
predicate_ctor CCounter_nonzero (RWCounter c) () =
c.N |-> ?v &*& c.MAX |-> ?m &*& v > 0 &*& m > 0 &*& v <= m;
predicate_ctor CCounter_nonmax (RWCounter c) () =
c.N |-> ?v &*& c.MAX |-> ?m &*& v < m &*& m > 0 &*& v >= 0;
predicate inv(RWCounter c) =
c.rl |-> ?rl &*& rl!=null &*& rlck(rl,1,CCounter_shared_state(c))
&*& c.wl |-> ?wl &*& wl!=null &*& wlck(wl,1,CCounter_shared_state(c))
&*& c.notzero |-> ?cc &*& cc !=null &*& cond(cc,CCounter_shared_state(c),CCounter_nonzero(c))
&*& c.notmax |-> ?cm &*& cm !=null &*& cond(cm,CCounter_shared_state(c),CCounter_nonmax(c));
@*/
public class RWCounter {
int N;
int MAX;
ReentrantReadWriteLock mon;
ReadLock rl;
WriteLock wl;
Condition notzero;
Condition notmax;
public RWCounter(int max)
//@ requires max > 0;
//@ ensures inv(this);
{
MAX = max;
//@ close CCounter_shared_state(this)();
//@ close enter_rwlck(CCounter_shared_state(this));
mon = new ReentrantReadWriteLock();
rl = mon.readLock();
wl = mon.writeLock();
//@ close set_cond(CCounter_shared_state(this),CCounter_nonzero(this));
notzero = wl.newCondition();
//@ close set_cond(CCounter_shared_state(this),CCounter_nonmax(this));
notmax = wl.newCondition();
//@ close inv(this);
}
public void inc()
//@ requires inv(this);
//@ ensures inv(this);
{
try {
//@ open inv(this);
wl.lock();
//@ open CCounter_shared_state(this)();
while (N == MAX)
/*@ invariant N |-> ?v &*& v >= 0 &*& MAX |-> ?m &*& m > 0 &*& v <= m &*&
notmax |-> ?cm &*& cm !=null &*&
cond(cm,CCounter_shared_state(this),CCounter_nonmax(this));
@*/
{
//@ close CCounter_shared_state(this)();
notmax.await();
//@ open CCounter_nonmax(this)();
}
N++;
//@ close CCounter_nonzero(this)();
notzero.signal();
} catch (java.lang.InterruptedException e){}
wl.unlock();
//@ close inv(this);
}
public int get()
//@ requires [?f]inv(this);
//@ ensures [f]inv(this);
{
//@ open [f]inv(this);
rl.lock();
//@ open [?q]CCounter_shared_state(this)();
int v = N;
//@ close [q]CCounter_shared_state(this)();
rl.unlock();
//@ close [f]inv(this);
return v;
}
public void dec()
//@ requires [?f]inv(this);
//@ ensures [f]inv(this);
{
try {
//@ open inv(this);
wl.lock();
//@ open CCounter_shared_state(this)();
while(N==0)
/*@ invariant N |-> ?v &*& v >= 0 &*& MAX |-> ?m &*& m > 0 &*& v <= m &*&
[f]notzero |-> ?cc &*& cc !=null &*&
[f]cond(cc,CCounter_shared_state(this),CCounter_nonzero(this));
@*/
{
//@ close CCounter_shared_state(this)();
notzero.await();
//@ open CCounter_nonzero(this)();
//@ assert N>=0;
}
N--;
} catch (java.lang.InterruptedException e){}
//@ close CCounter_shared_state(this)();
wl.unlock();
//@ close [f]inv(this);
}
}