Jump to content
  • Advertisement
Sign in to follow this  
Trapper Zoid

Event driven programming question

This topic is 4838 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

Sorry if this is a bit simple; I've been thinking about this problem today and I'm not that knowledgable about designing event driven programs (and my mind's not the clearest today). I'm also not really able to speak in the lingo, so I might be using the wrong terms. If I wanted to create a class that wants to communicate events to some non-pre-defined set of other classes when a event happens (such as the user pressing the "J" key, or after every 5 seconds etc), what would be the best way to send that data? Does the class keep a record of which classes would be interested in that kind of information in a big list (obviously the other classes would have to register for this list)? Or does the class send out a big signal on some sort of publically available part of memory for the other classes to check (kind of like a big noticeboard, I guess). Thanks in advance!

Share this post


Link to post
Share on other sites
Advertisement
A simple way is to make threeclasses. An event manager and an eventsubscriber interface and lastly a message.



class CMessage {
int nType;
void *pData;
};

class IEventSubscriber {
int message ( int nType, CMessage* pData );
};

class IEventManager {

// map <level, subscriptions_of_that_level>
std::map< int, vector< IEventSubscriber*> > mvSubscriptions;

unSubscribe(level, IEventSubscriber*);
subscribe (level, IEventSubscriber*);

sendMsg ( level, CMessage *);
};



Every class that you want to be able to recieve a message should be derived from IEventSubscriber. When you have initialized the class you call the Manager and tell it you want messages from level X (ie LVL_TIMER). The manager puts all subscribers in the mvSubscriptions list.

When a class some time later calls "sendMsg" with the level LVL_TIMER, the manager calls the "message" function in all the subscribers list of that level. Hence any subscriber can pick what type of messages it wants a reaction on.

A simple and easy to implement way of doing it.

Share this post


Link to post
Share on other sites
So if I understand correctly, there's an intermediatory class that acts a bit like a herald for communicating the messages, right?

So this herald class has the following properties:
- a list of classes to tell when a message is given (and the methods for adding and removing from this list)
- a way for it to be given messages to pass to the classes on the list.

That makes sense. But is there usually a herald message class for every type of message, or one big message manager class for handing all messages?

Thanks again!

Share this post


Link to post
Share on other sites
Quote:
Original post by Trapper Zoid
So if I understand correctly, there's an intermediatory class that acts a bit like a herald for communicating the messages, right?

So this herald class has the following properties:
- a list of classes to tell when a message is given (and the methods for adding and removing from this list)
- a way for it to be given messages to pass to the classes on the list.

That makes sense. But is there usually a herald message class for every type of message, or one big message manager class for handing all messages?

Thanks again!


Well since the sendMsg function takes a CMessage * as parameter you just inherit from that class.

something like this for sending the message to all classes that wants the timer message. In the Message function of the subscriber you just cast the message to the prefered type. So short answer. One manager for all messages. The subscriptionpart is just so that you do not have to send all messages to every reciever. Only those that subscribe on a certain level.



struct sMessage {
int nType;
void *pMsgData;
} tMessage;

struct sTimerMessage {
int nType
time_t time;
};

....
tTimerMessage aTimerMsg;
aTimerMsg.type = EVENTMSG_TIMESTAMP;
aTimerMsg.time = gettime();

sendMsg ( EVENT_TIMER, (tMessage*)&aTimerMsg );
....

void sendMsg ( int nLevel, tMessage * pMessage ) {
std::vector<IEventReciever*>::iterator it = this->m_vEventRecievers[nType].begin();
std::vector<IEventReciever*>::iterator itEnd = this->m_vEventRecievers[nType].end();

// Send the message to all recievers in the nLevel vector
while ( it!=itEnd ) {
((IEventReciever*)*it)->Message( nType, pMessage );
it++;
};
};


Share this post


Link to post
Share on other sites
Quote:
Original post by Zorak

Every class that you want to be able to recieve a message should be derived from IEventSubscriber.

It would probably be better to have IEventSubscriber as a member of those objects instead if deriving from it, It’s simpler to manage especially when you want to have you objects derived from other base classes. This way you won’t be dealing with multiple inheritance which can get messy.

Share this post


Link to post
Share on other sites
Quote:
Original post by Grain
Quote:
Original post by Zorak

Every class that you want to be able to recieve a message should be derived from IEventSubscriber.

It would probably be better to have IEventSubscriber as a member of those objects instead if deriving from it, It’s simpler to manage especially when you want to have you objects derived from other base classes. This way you won’t be dealing with multiple inheritance which can get messy.


Then how do you propose to store them in the manager? In the example i store a vector of IEventSubscriber*.

Share this post


Link to post
Share on other sites
Quote:
Original post by Zorak
Well since the sendMsg function takes a CMessage * as parameter you just inherit from that class.


I'm not sure what you mean by inheritance in this case, but I can see how you can pass an identifier within the CMessage class to tell a singleton event manager class which destination classes to send the event to.

Thanks Zorak! I knew I'd seen this implementation somewhere before, but I'd forgotten how it was done. I'm sure I can come up with a workable solution now.

Share this post


Link to post
Share on other sites
Quote:
Original post by Zorak
Quote:
Original post by Grain
Quote:
Original post by Zorak

Every class that you want to be able to recieve a message should be derived from IEventSubscriber.

It would probably be better to have IEventSubscriber as a member of those objects instead if deriving from it, It’s simpler to manage especially when you want to have you objects derived from other base classes. This way you won’t be dealing with multiple inheritance which can get messy.


Then how do you propose to store them in the manager? In the example i store a vector of IEventSubscriber*.

In the same way. In this case it those pointers would point to a member of the object instead of the object it self.

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!