/* Distributed Termination Detection - Dijkstra/Safra */ mtype = { Query, Quit, Work }; chan q[2] = [32] of { mtype, byte }; active [2] proctype N() { bool query_in_progress = false; byte s, r, n; assert(_pid == 0 || _pid == 1); q[1 - _pid]!Work,0; s++; /* seed some work items */ accept: do :: q[_pid]?Work,0 -> r++; if :: (s < 16) -> q[1 - _pid]!Work,0; s++ :: true fi :: empty(q[0]) && !query_in_progress && _pid == 0 -> /* only node 0 can initiate termination */ query_in_progress = true; /* remember that we sent the Query msg */ q[1]!Query,s :: q[_pid]?Quit,0 -> /* only node 1 receives this */ assert(_pid == 1); break /* 1 can now terminate */ :: q[_pid]?Query,n -> if :: _pid == 1 -> q[0]!Query,r /* respond to termination query from 0 */ :: _pid == 0 -> /* process response to our termination query */ if :: n == s -> q[1]!Quit,0; break /* accepted; node 0 terminates */ :: else -> query_in_progress = false /* rejected; try again */ fi fi od; assert(empty(q[_pid])) }