Hi,
Crazed123 wrote:Also, if one implemented the blocking/non-blocking of sending threads in the kernel, could one implement mutual exclusion via the message-passing system? If one could, it would be nice to write programs in terms of synchronizing IPC and let the operating system handle the down-and-dirty mutual exclusion work internally.
You could implement mutual exclusion via. messaging-passing. If there's only 2 threads involved then a thread can send a "give me the lock" message to the other thread if it doesn't already have it. You could also implement a "lock manager" that accepts "give me lock X" messages and "I'm finished with lock X messages".
However, in my experience software that's designed for message passing never needs mutual exclusion. It's a bit hard to explain, but instead of asking yourself "how do I protect FOO from multiple threads" you end up asking yourself "how do I split FOO across multiple threads so no data is shared".
In general I use one of 2 different approaches - "pipelining" (where each thread does some processing and sends it's results to the next thread in the pipeline), or "encapsulation" (where all operations that effect a piece of data are shifted into a seperate thread and other threads ask this thread to do any operations on the data instead of doing the operations themselves).
Pipelining works well if you're converting data from one or more formats into one or more other formats (I'm currently messing with a compiler/assembler implemented as 5 or more stages). Encapsulation works well when pipelining isn't suitable.
For an example, consider a word-processor. At the middle of the word-processor you might have a "document thread" that stores the current document and does all operations on that document. Then you could use pipelining when a file is opened, with one thread that reads the data from disk and sends it's output to a conversion thread, and a conversion thread that converts the data into a common format and sends it to the document thread. The same can happen when a file is saved (the document thread sends the data to a conversion thread that sends the data to a "write file/s" thread).
Then you'd have a "user interface" thread that interacts with the document thread, where the user interface thread asks the document thread to do modifications and searches, and the document thread sends data that should be displayed to the user interface thread.
If the document thread becomes a bottleneck, you could split it into several threads (e.g. one document thread per 1000 lines). If you want a multi-user word-processor you can use multiple user interface threads (I've done this before).
With non-blocking messaging, it's possible to have everything happening at the same time - e.g. while a document is being loaded from disk it can be being converted into a common format, being inserted into the document, being displayed and modified by the user as it becomes available, being converted into another format and being saved to disk.
All of this can be done without any mutual exclusion (or traditional locking of any kind).
Cheers,
Brendan