// if we have a blocking areceive (not an nbreceive) we first need to convert // it to a non blocking (busy waiting) receive. // if the message delivery policy is not FIFO this approach would certainly // lead to starvation as real incoming messages would always be shadowed by // dummy ones. This is the best that can be accomplished with the given // constraints. bool skip = false; // areceive to nbreceive T | None nbreceive(pid_t p) { if(!skip) asend((get_pid(), null), get_pid()); // always have something from myself // to read when no messages are incoming (pid, data) = areceive(p || get_pid()); // chiaramente meh, ma ci sono alternative if(pid == get_pid() && data == null) { skip = false; return None; } // a meaningful message has been receive. on the next call we won't be // needing a new dummy message to be sent as there'll be already one in queue. skip = true return data } // overriding asend to comply to the above-defined message format void asend<T>(T data, pid_t p) { asend((get_pid(), data), p); } // now the required pssend can be implemented void pssend<T>(T data, pid_t p) { // referring to the one implemented above asend<T>((get_pid(), data), p); (pid_t, T) data; while((data = areceive(p)) && data.second != ACK) asend(data, get_pid()); } T | None psreceive(pid_t p) { res = nbrecieve(p); if(res != None) { asend(ACK, res.first); return res.second; } return None; }