Advice on a message handling system - c++

I'm currently putting together a game engine as part of a university module and one part of it is a message handling system. I'm looking to improve on the lecturer's implementation, so any advice or criticism of my possible changes is most welcome.
Current Message structure
struct Message
{
Entity* entity;
std::string message;
void* data;
Message(Entity* entity, std::string message, void* data):
entity(entity), message(message), data(data) {}
};
The initial implementation only has messages being sent to Entities, but I plan on using an 'interface' to allow any component of the game engine to be able to receive messages.
class IMessageReceiver
{
public:
virtual void handleMessage(const Message& message) {}
};
struct Message
{
IMessageReceiver* receiver;
std::string message;
void* data;
};
//examples
class Entity : public IMessageReceiver { };
class Game : public IMessageReceiver { };
A problem I have with the current system is the void* for the data (I just don't like using void*). This is then cast to the type it needs to be inside the handleMessage function as I know what data it should be receiving (depending on the message string)- typically it has been either a 3D vector or an Entity up to this point, but if I have it sending messages to things other than Entities then this will likely change.
I wanted to change this to use a template instead; however, I'm not sure how I'd go about doing this.
template <typename T>
struct Message
{
IMessageReceiver* receiver;
std::string message;
T* data;
};
I'm somewhat familiar with templates, on a basic level, but I'm likely lacking some deeper knowledge of template trickery. I know I could pass it the type of the data when I create a new message.
//example
Entity* entity;
vec3 someVec;
Message<vec3> message(entity, "Fire", someVec);
MessageHandler::sendMessage(message);
But how would I then write up the handleMessage function declaration in IMessageReceiver, as different implementing classes will have different data in the messages sent to them?
virtual void handleMessage(const Message<?>& message) {}
I had the thought of making IMessageReceiver a template class as well, so when a class inherits from it they set the type of data the messages they receive will be.
template <typename T>
class IMessageReceiver
{
public:
virtual void handleMessage(const Message<T>& message) {}
};
class Entity : IMessageReceiver<vec3> {};
However, this means that a message receiver can only receive information of one type, but there could be an occasion where I might have to send data of different types to the same receiver- for example, a derived class of Entity usually receives a vec3 as the data part of the message but a new scenario requires it to receive another Entity.
Another issue with this I found is that only the abstract base class Entity inherits from IMessageReceiver (not every derived class of Entity and they receive different information of different types- or could), which would then mean making Entity a template class as well so this could be set by passing it on. But I would still have this inflexible system where something can only receive messages of one type of data.
Perhaps void* is the 'best' approach, and perhaps using an interface class is not. I don't know.
Please feel free to offer up any constructive criticism you can think of. I'm not asking someone to write it for me, I'm just looking for advice on a good way of implementing what I'm attempting to do. Basically, I want to be able to make any component of the engine be able to receive messages; the data that is sent in the message is not predefined; and preferably does not use void*.
Thank you for taking the time to read this. If you require any additional information please let me know.
Gavin

Virtual functions require the exact signature to be known at compile time, so you cannot use "template trickery" directly to achieve what you want.
Take a look at Boost.Any as a replacement for the void* Message::data. It still requires a cast of sorts to convert it to the correct type, but it is done in a type safe manner. Also, this way the message "owns" the data so you don't have to worry about lifetime issues.
Also, instead of using IMessageReceiver, consider std::function<void(const Message&)> instead. That way, you can pass the message to any object that has a void operator()(const Message&), and you don't have bother with the complexity of a hierarchy.
Both boost::any and std::function internally use a technique known as type erasure which takes the inheritance out of the interface and allows you to treat things as values, which tends to make the code simpler to reason about.

Your pattern suggests that the sender knows the receiver and will send the message directly to a single receiver, so you could have the sender simply call the receiver's method directly and that method could be overloaded with "message"-specific parameters (which also solves the problem of which object "owns" the dynamically allocated message data).
A common reason for making a messaging system rather than directly calling methods on the target is to reduce coupling between objects. The observer or publish/subscribe pattern reduces coupling by making the senders of messages (mostly) unaware of the receivers of the messages. In this case, you need a way to abstract message details, which seems to be what the question is about.
You could have a virtual base class for a message, and derive message-specific types from it. The handleMessage method could then take a pointer to the base class, and then use a dynamic_cast to downcast it to the concrete message type. This is slightly nicer than passing a void* and doing an arbitrary cast, as you'd at least get some run-time type checking.
Another option is to have multiple overloads in your IMessageReceiver interface (which all have no-op implementations) and to have message senders simply call the specific method directly. This gives you compile-time type checking, but requires a recompile whenever you invent a new "message" type. (I put message in quotation marks because, in this scheme, you no longer need message objects.)

Related

Implementing a pure virtual function Change parameter from void* to specific type pointer

I have a base Class that implements all the mundane stuff with creating a server which spawns a thread, listens on a queue and processes the received messages.
Those messages are then given to a pure virtual function:
void ProcMsg(void* msg) = 0;
In the implementation of the derived Class when implementing the ProcMsg I would like to change the void* msg to a pointer to as specific message structure definition MyMsgType* msg. Is there a language construct that would allow me to do that or is the only way to re-cast the void* to MyMsgType* inside of the ProcMsg implementation.
The only thing I found is Templates, but I was hoping there would be a simpler way.
If you're using void * for any other reason beyond interfacing with some ancient C library, you probably want to rethink your architecture.
I would create a base class for all the messages that be passed and then have a virtual method on those called process or something like that. If that turns things around too much, then you might have to have a messageType field and query it, then do some typecasting.

Design help- Design pattern for handling a generic interface for different types of messages

I have to bring up an interface for a node which can receive messages with same header but different message types. The message type comes at a fixed position in the header always. These message types can further be divided into two classifications - Atype(a set of 6 messages) and Btype(a set of 8 messages). The design needs to provide support to add a new message type (eg Ctype) to the interface easily. I have been thinking of writing an interface class which has a std::map with message_type being Atype or Btype and the message_handler_type is a function call to the corresponding message handlers(based on two singleton classes for AtypeMessage and BtypeMessage) - AtypeMessage::get_instance()->AtypeMessageHandler() or BtypeMessage::get_instance()->BtypeMessageHandler() and pass the message along to the corresponding message handler based on the message_type. This node will receive huge amount of traffic.
Will this be a good enough design for future extension?
Is there any other good design options that I am missing out?
You can make a base class for your messages:
class Message {
public:
virtual void do_something() = 0;
};
class MessageA : public Message {
public:
void do_something() override {
// ...
}
};
and inherit all other messages from the base one (like MessageA does in the example). Than you'll be able to use them like
void recieve_message(Message&) {
// ...
};
It also provides a useful method for extension: you can just add another class derived from Message.
I'm sorry if I misunderstood something: the question seemed really messy to me.

Which is better: Function overriding or passing a function pointer for event handling

So, I'm writing code for a class that will go into a library that will be used by others. This class will intercept and process incoming messages (details are not important but it's using the activemq-cpp library). The outline of this consumer class is
class MessageConsumer {
...
public:
void runConsumer();
virtual void onMessage(const Message* message);
}
where runConsumer() sets up the connection and starts listening and onMessage() is called when a message is received.
My questions is this: People who'll use this code will each have their own way of processing the different messages. How can I keep MessageConsumer generic but offer this flexibility, while keeping their code simple?
Two options:
Should they inherit a new class from MessageConsumer and write their own onMessage()?
Should they pass a pointer to a message handling function to MessageConsumer?
What do you think, which option is better and why?
Thanks!
In one approach, clients are allowed to register a callback and then the MessageConsumer invokes the registered callback. This is something like an observer/broadcast design pattern.
The second approach, where clients have to inherit and override MessageConsumer would be something like Strategy design pattern.
Basic design goals suggest to use the weakest relationship to promote loose coupling. Since inhertiance is a stronger relationship as compared to a simple association, everything else being the same Approach 1 is preferred.
From Herb's article
"Inheritance is often overused, even
by experienced developers. Always
minimize coupling: If a class
relationship can be expressed in more
than one way, use the weakest
relationship that's practical. Given
that inheritance is nearly the
strongest relationship you can express
in C++ (second only to friendship),
it's only really appropriate when
there is no equivalent weaker
alternative."
But as James points out, it is tough to comment unless the overall design constraints are known clearly.
Inheritance will make your library more OO-friendly and may improve readability. But really, the choices are about the same since the compiler will check that the user has supplied the function (assuming you declare a pure virtual handler in the base class), and the underlying mechanism will be accomplished via a pointer anyway (virtual table in the case of inheritance).
Pure virtual functions allow the compiler to check that the client code implements the handler. Virtual dispatch is active immediately after an object is constructed, and someone looking at the derived class can reason accurately about its handling. Data needed for the handling can be conveniently and clearly grouped into the derived class. Factories can still select a particular derived class to instantiate.
Function pointers are run-time state, so there's a little more care needed to initialise them in a timely fashion, for optional run-time checks on their being set and error handling, and to reason about which set is in effect during program execution. With that comes more freedom to vary them within the lifetime of the object.
A third alternative is a template policy class, or the Curiously Recurring Template Pattern, to lock in the behaviours at compile time. This potentially allows inlining of callbacks, dead-code elimination and other optimisations.
virtual function or tepmlated functor are the way to go. These approaches give greater flexibility ad looser coupling than function pointer one.
To illustrate that - function pointer approach can be wrapped with first two, but not vice-versa.
void cbFunction();
class Interface {
virtual void act() =0 ;
};
class CbFuctionWrapper:public Interface {
public:
virtual void act() {cbFunction()};
};
class AnotherImpl: public Interface {
Context _c; // You can't pass additional context with usual function without downcasting, but OO is all about that.
public:
virtual void act() {...}
}

polymorphic handles

I have handles of different types inside a hierarchy.
class Handle { common data }
class HandleA : Handle { data specific to a }
class HandleB : Handle { data specific to b }
Most parts of the code only deal with handles. But some parts ( the "managers" for HandleA/HandleB ) need access to the data in the child classes.
eg:
void ManagerA::DoSomething(Handle handle)
{
// needs access to data in handleA
}
Are there any solutions to this that don't involve casting?
My ideas so far:
- Save the additional data inside a map in ManagerA/B and use the handle to lookup that data (additional hashtable lookup)
- Have polymorphic methods in the handles ( handle.DoSomething()) that call the appropiate manager methods (needs an additional pointer in every handle)
- Screw it and use casts
Any ideas? Am I missing something?
Thanks
Receiving an argument by value, as you're doing in:
void ManagerA::DoSomething(Handle handle)
WILL "slice away" anything in the passed-in argument beyond what a Handle instance holds, so your handle argument will have NO "extra data". You absolutely need to pass by pointer or reference (possibly const if the data does not need to be modified, of course).
That being said, the normal polymorphic approach involves defining virtual methods within the base class and overriding them appropriately in the subclasses. Why not follow such a perfectly normal architecture rather than fighting against the OO approach? There may be valid reasons (which justify e.g. adopting some variant on a visitor pattern, etc), but you just don't explain enough of the forces in play for us to be able to help along those lines; on the information as presented I'd have to suggest "rearchitect to use virtual methods".
If it's data specific to only one -- and only one type, use dynamic_cast<T>, that's what it's there for. Otherwise declare a virtual function in the base class.
EDIT: It's unlikely that any solution is going to result in measurable performance differences at runtime.
I wouldn't use polymorphism for handles - being handles rather than pointers, they are supposed to absolutely hide the implementation of the referenced object. If you use virtual functions, the user of the handle could call those functions, which is surely a bad idea.
The two common solutions are casting and using a map. If the later, your handle doesn't even have to be a class - it could just as well be an int or so. On Windows, handles are void* pointers. I have no idea what's really behind the pointer, but I really don't care. And that's the point of handles, as far as I'm concerned.
What about changing the signature for DoSomething to:
void ManagerA::DoSomething(HandleA handle)
Your first and third ideas would work. Another idea is to use double-dispatch (I don't know if that Wikipedia article is understandable: the original article/explanation in Meyer's More Effective C++ is 20-odd pages long), which means implementing a virtual method like Handle::DoSomething(Manager&).
Another possibility is storing the concrete type in each handle, possibly as an integer or an enum. You either hard-code all the possible concrete handle types, or use some sort of type registration mechanism. Obviously this approach has its own drawbacks, but it is another possibility, one you didn't mention. It's the approach X-Windows used for event types. The event data structure was a union of all possible event data, with a type variable indicating the true data type of a particular event. Not saying it's good, just saying it's an option, one that doesn't require dynamic casting.
enum HandleType
{
HANDLE_TYPE_A,
HANDLE_TYPE_B
};
class Handle
{
private:
HandleType _type;
protected:
Handle(HandleType type) :
_type(type)
{}
public:
HandleType get_type() const
{ return _type; }
};
class HandleA
{
HandleA() :
Handle(HANDLE_TYPE_A)
{}
};
void ManagerA::DoSomething(Handle& handle)
{
if (handle.get_type() == HANDLE_TYPE_A)
do_something();
}

How can I manage a group of derived but otherwise Unrelated Classes

It seems the more I talk about this problem the better I understand it. I think my previous question didn't convey what I am trying to do correctly. My apologies for that.
In my design I have GameObjects which are essentially an aggregation class, all functionality in a GameObject is implemented by adding various "Features" to it. A Feature is a Subclass of the Feature class that has it's own members and functions. All Features can receive Messages
class Feature
{
public:
virtual void takeMessage(Message& message) = 0;
};
class VisualFeature : public Feature
{
public:
void takeMessage(Message& message);
private:
RenderContext m_renderer;
};
... Additional Features ...
FeatureServers are objects that are responsible for coordinating the various Features. GameObjects can subscribe to FeatureServers to receive messages from them, and Features can Subscribe to GameObjects to handle the messages it is interested in.
So for example in this code:
GameObject Square;
VisualFeature* SquareSprite = new VisualFeature();
Square.subscribe(SquareSprite, "MESSAGE_RENDER");
Square.addFeature(SquareSprite);
m_VisualFeatureServer.subscribe(Square, "MESSAGE_RENDER");
The VisualFeatureServer sends the message tied to "MESSAGE_RENDER" which may look something like this
class Message
{
public:
std::string getID() {return m_id;}
bool isConsumed() {return m_consumed;}
void consume() {m_consumed = true;}
protected:
bool isConsumed;
std::string m_id;
}
class Message_Render : public Message
{
public:
Message_Render() : m_id("MESSAGE_RENDER"), m_consumed(false) {}
RenderTarget& getRenderTarget() {return m_target;}
private:
RenderTarget& m_target;
};
When the VisualFeatureServer sends the Message_Render class to the Square GameObject it then forwards it to any FeatureComponents that are subscribed to receive that particular message. In this case the VisualFeature class receives the Message_Render message. Here is where my problem is, the VisualFeature class is going to receive a Message& that it can tell is a Message_Render by it's ID, I want to be able to treat it as a Message_Render rather then a Message like so:
void VisualFeature::takeMessage(Message& message)
{
//Here's the problem, I need a pattern to handle this elegantly
derivedMessage = convertMessageToDerivedType(message);
this->handleDerivedMessageType(derivedMessage);
}
void VisualFeature::handleDerivedMessageType(Message_Render& message)
{
message.getRenderTarget().render(m_renderer);
message.consume();
}
Is there a way to elegantly deal with the takeMessage portion of this design?
The other answer was getting too bloated with edits, so I started a new one.
The casting you are doing in the receiveMessage() functions is definitely a code smell.
I think you need to use a combination of:
Abstract factory pattern to instantiate your objects (messages and components)
Observer pattern to respond to messages
The idea is that each component type will only subscribe to messages of its own type, and will therefore only receive messages intended for it. This should eliminate the need for casting.
The notifying object could, as an example, use a vector of notifier objects indexed by the message ID. The observing object (the derived component class) could subscribe to the particular notifier indexed by its own message ID.
Do you think this design pattern would help?
I'm not sure that I really understand your question, and I think you need to clarify what you are trying to achieve more.
Just a few other comments though.
I don't think public inheritance (as you have implemented) is the best design pattern to use here. The golden rule with public inheritance is that it should only be used if the derived class truly "is a" object of the base class.
One of the main benefits of using inheritance in C++ is to implement polymorphism where (for example) you have a list of pointers to Base objects and you invoke methods on those objects, and they are dispatched to the relevant VisualComponent and PhysicsComponent object methods as appropriate.
Since (in your words) they have "unrelated class interfaces", you won't get any of the benefits of polymorphism.
It sounds like you are really inheriting from the Base class to implement the Mixin pattern.
Maybe composition is the better approach, where you include a copy of the Base class (which you will have to rename) in the VisualComponent or PhysicsComponent class.
However, based on the following question:
If I only have a reference or pointer
to Base what design options do I have
to expose the interface of
VisualComponent or PhysicsComponent?
Isn't the GameObject class (which you are instantiating in main()) already doing this for you?
Edit:
Okay, I think I understand better now that the question has been edited.
But I need some way to store all of
the Components dynamically in the
GameObject but still be able to use
their individual interfaces.
The only easy way I can see this working is by creating a virtual method in Base which is overridden in each derived class and implements class specific behaviour. GameObject could simply store a container of Base pointers and invoke the virtual method(s) which will be dispatched to the derived classes.
I would also recommend making Render(), Move() and any non-virtual methods private so that the GameObject class can only access the public (virtual) methods. The helps keep the public interface clean.
I'm not sure if this helps.
Edit 2:
After further discussion in the comments, it sounds like the factory pattern or the abstract factory pattern is what you need.
Visitor Pattern. If I understand what you are asking.
Though really need to know more context!
Take a look at boost.signals
You can define a signal for each message type and allow features to add slots (receivers) to it, this may be their member-functions of any name, or any other callable things of a proper signature.