I was reading an article from a back issue of Game Developer (August 2007, I believe) wherein several prominent programmers were discussing a wide range of topics. Not surprisingly, the discussion found its way to the problem of multi-threading. One of the programmers described an approach which I found quite interesting and practical. Programmers at his studio designed systems (sound, rendering, physics, etc..) as if they existed in their own memory space (or with as little memory shared as possible) and that systems communicated not by calling each other’s methods, but by passing messages which are queued and handled by the system in a linear fashion. The memory bit is fairly obvious, but the message passing thing sounded really cool.
This approach decouples method invocation from method execution (much like Objective-C does) and feeds the messages to the system one at a time. This guarantees that the system will execute instructions in sequence. A little time on Google and I found that this idea is a very well established design pattern called the “Active Objects” pattern. I found a great example of this pattern implemented in Python here.
In the Active Objects pattern, a “passive” object is wrapped by an “active” one, which forwards message objects to it from a queue. Messages are generated and enqueued by a “proxy” object, which implements the public interface of the system and exists in the client’s thread. Once one of the proxy’s methods is called, a “future” object (I called it an AsyncResult object like in the Python example) is returned. Once the system has processed the message, the return data (if there is any) is placed in the future object to be retrieved and used in the client thread.
This pattern is by no means a silver bullet, but it helped quite a bit in my code-base by providing a generic solution to threading that can accommodate lots of different types of interfaces and special cases and which protects against race conditions without excessive mutex use.