Perfect channels
A perfect channel is just a FIFO queue
Get blocks if the queue is empty
VAR q := (SR -> Q){* -> {}} % all initially empty
APROC Put(sr, m) = << q(sr) := q(sr) + {m} >>
APROC Get(sr) -> M = << VAR m | m = q(sr).head => q(sr) := q(sr).tail; RET m >>
Henceforth we suppress the sr argument and deal with only one channel, to reduce clutter in the specs.