Sign in to follow this  

Designing a generic message handler.

This topic is 4836 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Ok, i need some suggestions on writing a generic message handler. What i want to do, is make some sort of registration class, which connects simple integers (message ids) to a method of any class i want. Example: Pseudo code
CRegistration::GetInstance()->Register(ID_NAME_CHANGED, Game.DrawName());
CRegistration::GetInstance()->Register(ID_NAME_CHANGED, Network.SendNameToPlayers());
I want to map multiple methods to the same ID, which i can establish by using a std::multimap. Now i can post a message from anywhere in my application and all the registered functions will be called for the ID which whas posted.
CRegistration::GetInstance()->PostMessage(ID_NAME_CHANGED);
The real problem lies in storing the pointer to member functions. So i've come up with another method. The idea is to create an interface with the function operator:
class CFunction
{
public:
    void operator()() = 0;
};
Now i can derive my classes from the CFunction object. The only real big drawback is that i can only support one function of a class. So i can't do this anymore: Pseudo code
CRegistration::GetInstance()->Register(ID_FIRE, Game.PlayAnimation());
CRegistration::GetInstance()->Register(ID_FIRE, Game.CheckCollision());
It's kind of hard to explain, i hope this makes sense and someone knows of a solution to this rather complicated problem. Maybe there's a desing pattern which helps me with this?

Share this post


Link to post
Share on other sites
My message handling almost always had a generic IMessageHandler base.



class IMessageHandler
{
public:
int handleMessage( int messageID, MsgParam *param ) = 0;

};

class SoundSystem : public IMessageHandler
{
public:

int handleMessage( int messageID, MsgParam *param )
{
switch(messageID)
{
case SOUNDMSG_PLAY:
// play sound, getting paramters from struct
return 1;

case SOUNDMSG_STOP:
// same
return 1;
}

return 0;
}

};







Then you'd have a message system which would allow you to register messages...


//
MessageSystem::registerMessageHandler( int messageID, IMessageHandler *handler );

// example:

Game::init()
{
SoundSystem *ss = new SoundSystem;

MessageSystem::registerMessageHandler( SOUNDMSG_PLAY, ss );
MessageSystem::registerMessageHandler( SOUNDMSG_STOP, ss );

}






Or better yet, allow the system itself to register its own messages...


class SoundSystem : public IMessageHandler
{
public:
SoundSystem()
{
MessageSystem::registerMessageHandler( SOUNDMSG_PLAY, this );
MessageSystem::registerMessageHandler( SOUNDMSG_STOP, this );
}



// ....


};







The MessageSystem simply iterates the message queue, dispatching messages to the registered handlers. For extra functionality you could register the handlers based on priority and whether the message is SHARED or EXCLUSIVE, allowing you to have handlers which 'hog' messages (such as a GUI).

Perhaps my method is different to what you were working on, I based mine upon a flipcode article about Console System Handlers by Gaz Iqbal - but it's an idea to get you started.

Share this post


Link to post
Share on other sites
Boost::Bind and Boost::Function are overkill and a great way to add ten seconds to your compile time. YMMV of course.


class Function
{
public:
virtual ~Function()
{
}

virtual void operator()() = 0;
};

template<typename T>
class ConcreteFunction
{
public:
explicit ConcreteFunction(T* instance, void (T::* memFunc)()) :
_instance(instance),
_memFunc(memFunc)
{

}

void operator()()
{
(_instance->*_memFunc)();
}

private:
T* _instance;
void (T::* _memFunc)();
};

template<typename T>
ConcreteFunction<T>* MakeFunction(T* instance, void (T::* memFunc)())
{
return new ConcreteFunction<T>(instance, memFunc);
}

// usage
Foo* foo = new Foo();
Function* fn = MakeFunction(foo, &Foo::Bar);
(*fn)(); // calls foo's Bar() member function;
delete fn;
fn = MakeFunction(foo, &Foo::Stuff);
(*fn)(); // calls the foo instance's Stuff() member function


Remember to delete the pointers when you're done! Or make a wrapper class to do that for you.

Disclaimers:
Off the top of my head, probably won't compile, etc, etc

Share this post


Link to post
Share on other sites

This topic is 4836 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this