Message Passing

This is fundamental to understand, for building something like ROS. I think I have a high level good understand, but what I am learning in SE350 will help solidify this knowledge.

The following are different characteristics that we need to understand:

  1. Synchronization
  2. Addressing (direct vs. indirect)
  3. Format
  4. Queuing discipline

The 2 primitives:

send (destination, message)
receive (source, message)

1. Synchronization

Processes need to be synchronized to enforce Mutual Exclusion.

Both the sender and receiver can be blocking or nonblocking.

3 most common combinations:

  1. Blocking send, blocking receive (called a rendezvous): Both sender and receiver are blocked until message is delivered
  2. Nonblocking send, blocking receive: Sender continues on, Receiver is blocked until the requested message arrives
  3. Nonblocking send, nonblocking receive: Neither party is required to wait

2. Addressing

Direct addressing

  • Send primitive includes a specific identifier of the destination process
  • Receive primitive could know ahead of time from which process a message is expected
  • Receive primitive could use source parameter to return a value when the receive operation has been performed

Indirect addressing

  • Messages are sent to a shared data structure consisting of queues
  • Queues are called mailboxes
  • One process sends a message to the mailbox and the other process picks up the message from the mailbox

3. Message Format

4. Queuing Discipline

The simplest queueing discipline is first-in-first-out, but this may not be sufficient if some messages are more urgent than others. An alternative is to allow the specifying of message priority, on the basis of message type or by designation by the sender. Another alternative is to allow the receiver to inspect the message queue and select which message to receive next.

Example

Solving the Producer-Consumer Problem using messages.

const int
capacity = /* buffering capacity */ ;
null = /* empty message */ ;
int i;
void producer() {
  message pmsg;
  while (true) {
    receive (mayproduce,pmsg);
    pmsg = produce();
    send (mayconsume,pmsg);
  }
}
void consumer() {
  message cmsg;
  while (true) {
    receive (mayconsume,cmsg);
    consume (cmsg);
    send (mayproduce,null);
  }
}
void main() {
  create_mailbox (mayproduce);
  create_mailbox (mayconsume);
  for (int i = 1;i<= capacity;i++) send (mayproduce,null);
  parbegin (producer,consumer);
}