Jump to content
  • Advertisement
Sign in to follow this  
Nixsos

Designing a generic message handler.

This topic is 5121 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
Advertisement
On flipcode, there is a tip of the day called Event Binding to Class Methods that covers pretty much exactly what you want I think, but the comments indicate that the boost library has such functionality somewhere and it'd probably be a better idea to use the tried and true boost version.

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
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!