Now that we've seen the basic concepts involved in message passing, and
learned that even common everyday things like the C library use it, let's
take a look at some of the details.
Architecture & structure
We've been talking about clients and servers. I've also used three key phrases:
The client
The client wants to send a request to a server, block until the server has completed the request, and then when the request is completed and the client is unblocked, to get at the answer.
The server
Now that we've seen the client, let's look at the server. The client used ConnectAttach() to create a connection to a server, and then used MsgSend() for all its message passing.
Identifying messages
While the message-passing APIs transfer buffers of bytes without caring about the content, the client and server almost always care.
The send-hierarchy
One thing that's perhaps not obvious in a message-passing environment is the need to follow a strict send-hierarchy. What this means is that two threads should never send messages to each other; rather, they should be organized such that each thread occupies a level; all sends go from one level to a higher level, never to the same or lower level. The problem with having two threads send messages to each other is that eventually you'll run into the problem of deadlock; both threads are waiting for each other to reply to their respective messages. Since the threads are blocked, they'll never get a chance to run and perform the reply, so you end up with two (or more!) hung threads.
Receive IDs, channels, and other parameters
We haven't talked about the various parameters in the examples above so that we could focus just on the message passing. Now let's take a look.
Multipart messages
Until now, we've shown only message transfers happening from one buffer in the client's address space into another buffer in the server's address space. (And one buffer in the server's space into another buffer in the client's space during the reply.)