Message Queue Design

Started by
2 comments, last by AverageJoeSSU 14 years, 8 months ago
I'm working on a simple game architecture, and I've run into a design problem. Google has given me some help, but nothing specifically game related. Basically, I want to make use of a message queue to cut down on the level of interdependence between objects. So instead of object A directly calling a function of object B, object A would put a message in the queue which object B would listen for. The problem is that I'm a little stuck on the design of the message queue system itself. Problems I currently need to resolve: 1. Do all objects place messages on a single 'super queue', or do I have separate queues for different types of events? 2. How do I implement the messages themselves? Do I have a parent 'message' class and implement each type of message as a child class? Do I have a single generic 'message' class with variable contents? Currently, I'm leaning towards the following implementation: A special message queue class which appears to be a single 'super queue' to outside classes. Internally, it will have separate sub-queues for specific message types (a queue for sound messages, a queue for user input messages, etc.), but external classes only see the 'SendMessage' and 'ListenForMessage' functions. Listeners can wait for messages from a specific sender, or messages of a specific type. A single generic message class. It consists of a few fields describing the message, and a 'message content' buffer. All the message queue really cares about is the message type and its size It's up to any listeners present to extract what it needs from the content buffer. A few convenience methods exist to make creating/extracting messages easier. Every game object which needs to send/receive data will have a 'MessageListener' component with a unique ID. This allows game objects to send messages to a specific recipient. So, for example, the physics engine can put a message on the queue to say "Entity with listener 138711, you have collided with solid terrain. Here is some information about the collision." Has anybody here had to design a message queue in the past? I suspect that this could really come back to bite me if I'm not careful with the design, and was looking for some pointers.
Advertisement
I would just try to mock something up independently and quickly to see how things go.

I think for your first question, there is nothing about the system that should explicitly define that behavior. It's up to the user to either use a single queue or multiple queues, one for each system. But all queues are the same code object.

For the message itself. I think having a base class interface which identifies itself by a message ID and possible the recipient ID would be a good way to start. The receiver would then up cast if necessary to extract data.

There is a zillion ways to do this, so i'd just get started with what ever comes to mind first. Hopefully it turns out well but if not, you shouldn't have spent too much time on it so you could scrap it easily and start over.
Having gone down this route, I suggest against it.

The problems I had with a message system were:

  • Type-safetey: If you decide to use a message base class from which your message types derive, then a lot of downcasting will be required. This is a sign of a poor design. Storing messages as void*'s is even worse.

  • Debugging: If messages are stored in queues then the message sending and receiving are separated temporally. It becomes hard to track what objects sent which messages and which objects received which messages. There may be hundreds or thousands of messages floating about between hundreds of objects.



Method invocation and message passing are equivalent with the addition that method invocation is type-safe. May I suggest boost.signals+boost.bind? Boost.signals separates callers from callees while preserving type-safety and allows for tracing between them. I've had great success implementing a combination of observer and mediator patterns, where objects can publish/subscribe to events without knowing the callees and callers, respectively.

See http://code.google.com/p/pong-sdl/source/browse/trunk/SignalBroker.hpp for an example.
The lua programming gems book has an example of an event system. Parts of it are in lua, but you could easily do the whole thing in C++.

link.. do a find for Event and you will see the chapter.

------------------------------

redwoodpixel.com

This topic is closed to new replies.

Advertisement