Complete this form and hit the "Save Changes" button!
5 ratings
Are you sure you want to delete this code? Please type DELETE in the box below to confirm.
Are you sure you want to verify this code?
Are you sure you want to publish this code?
Are you sure you want to unpublish this code?
Are you sure you want to autogenerate the summary + description for this code?
xxxxxxxxxx
// RUN: %dafny /compile:0 /dprint:"%t.dprint" "%s" > "%t"
// RUN: %diff "%s.expect" "%t"
class Node {
var left: Node?
var right: Node?
var parent: Node?
var anc: set<Node>
var desc: set<Node>
var sense: bool
var pc: int
predicate validDown()
reads this, desc
{
this !in desc &&
left != right && // not needed, but speeds up verification
(right != null ==> right in desc && left !in right.desc) &&
(left != null ==>
left in desc &&
(right != null ==> desc == {left,right} + left.desc + right.desc) &&
(right == null ==> desc == {left} + left.desc) &&
left.validDown()) &&
(left == null ==>
(right != null ==> desc == {right} + right.desc) &&
(right == null ==> desc == {})) &&
(right != null ==> right.validDown()) &&
(blocked() ==> forall m :: m in desc ==> m.blocked()) &&
(after() ==> forall m :: m in desc ==> m.blocked() || m.after())
// (left != null && right != null ==> left.desc !! right.desc) // not needed
}
predicate validUp()
reads this, anc
this !in anc &&
(parent != null ==> parent in anc && anc == { parent } + parent.anc && parent.validUp()) &&
(parent == null ==> anc == {}) &&
(after() ==> forall m :: m in anc ==> m.after())
predicate valid()
reads this, desc, anc
{ validUp() && validDown() && desc !! anc }
predicate before()
reads this
{ !sense && pc <= 2 }
predicate blocked()
{ sense }
predicate after()
{ !sense && 3 <= pc }
method barrier()
requires valid()
requires before()
modifies this, left, right
decreases * // allow the method to not terminate
//A
pc := 1;
if(left != null) {
while(!left.sense)
modifies left
invariant validDown() // this seems necessary to get the necessary unfolding of functions
invariant valid()
decreases * // to by-pass termination checking for this loop
// this loop body is supposed to model what the "left" thread
// might do to its node. This body models a transition from
// "before" to "blocked" by setting sense to true. A transition
// all the way to "after" is not permitted; this would require
// a change of pc.
// We assume that "left" preserves the validity of its subtree,
// which means in particular that it goes to "blocked" only if
// all its descendants are already blocked.
left.sense := *;
assume left.blocked() ==> forall m :: m in left.desc ==> m.blocked();
if(right != null) {
while(!right.sense)
modifies right
// analogous to the previous loop
right.sense := *;
assume right.blocked() ==> forall m :: m in right.desc ==> m.blocked();
//B
pc := 2;
if(parent != null) {
sense := true;
//C
pc := 3;
while(sense)
modifies this
invariant validUp() // this seems necessary to get the necessary unfolding of functions
invariant left == old(left)
invariant right == old(right)
invariant sense ==> parent != null
// this loop body is supposed to model what the "parent" thread
// might do to its node. The body models a transition from
// "blocked" to "after" by setting sense to false.
// We assume that "parent" initiates this transition only
// after it went to state "after" itself.
sense := *;
assume !sense ==> parent.after();
//D
pc := 4;
left.sense := false;
//E
pc := 5;
right.sense := false;
//F
pc := 6;