Jump to content
  • Advertisement
Sign in to follow this  
lexs

Event/Message ID

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

I'm having problems deciding what would be the best way to deal with event id's in my system. I want to avoid a big single enum for obvious reasons. Defining the ID by hand is error prone. As simple strings would bring to much overhead what i'm leaning to now is using an integer hash from the event name. But i want to avoid having the hash recomputed all the time so this is my thought:
typedef Hash EventID;

class Event
{
public:
	virtual const EventID & getEventID() const = 0;
};

class SomeEvent : public Event
{
public:
	static EventID ID;
	virtual const EventID & getEventID() const { return ID; }
};

// Implementation
EventID SomeEvent::ID("SomeEvent");


Is this a good way, is there any better? PS I don't want to use something like boost::bind to implement synchronous events, ie signals.

Share this post


Link to post
Share on other sites
Advertisement
There's no need for virtuals.

class Event {
public:
Event(const EventID & id)
: id(name)
{}
private:
EventID id;
};

class EventID {
public:
EventID(const char * name)
: hash(calculateHash)
{}

EventID(const EventID & other)
: hash(other.hash)
{}

// copy operator

private:
int hash;
};

Then:

class MyCustomMessage : public Event {
public:
MyCustomMessage()
: Event(ID)
{}
static EventID ID;
};
// ----

EventID MyCustomMessage::ID("MyCustomMessage");

Share this post


Link to post
Share on other sites
It really depends on what your ID is used for - maybe you can share a few use cases?

It seems to me like you're using it as the "type" of the event. In that case are you going to use downcasts after checking the type?

Share this post


Link to post
Share on other sites
Quote:
Original post by Antheus
There's no need for virtuals.

That depends if you want to add the id member to every object or not. But good point.

Quote:
Original post by Ahnfelt
In that case are you going to use downcasts after checking the type? If so, there are object oriented / statically typed ways of solving this that you might want to look into.

Yes, it would be used as a type for casts. This would probably be done in the backend using thunks rather than user code though.
But i'm interested in the other ways. Please share.

Share this post


Link to post
Share on other sites
Quote:
Original post by lexs
Quote:
Original post by Ahnfelt
In that case are you going to use downcasts after checking the type? If so, there are object oriented / statically typed ways of solving this that you might want to look into.

Yes, it would be used as a type for casts. This would probably be done in the backend using thunks rather than user code though.
But i'm interested in the other ways. Please share.


Polymorphism is the obvious alternative. You'd have to share a little more about exactly what you're trying to accomplish before anyone could give you specific advice.

If you're sending these events from one subsystem to another, perhaps one option is the Command pattern, where the receiving subsystem could call command->execute(this), which would call the appropriate methods on the subsystem.

Or if these events are broadcast, blend in the Visitor pattern and have executeAudio, executePhysics, executeRenderer, etc. So if you have a GrenadeExplosionEvent, it could define exactly how it affects each subsystem.

But I have no idea if this is relevant to what you're using "events" for.

Share this post


Link to post
Share on other sites
Quote:
Original post by drakostar
You'd have to share a little more about exactly what you're trying to accomplish before anyone could give you specific advice.


The events will basically be send from one subsystem to (several) others. When you send the event you won't specify an explicit receiver as all subsystems can register which events they care about. So the type/id will be used by the receiving subsystem to see which event it has received.

You can say that the subsystems have a update() function where they poll for received events instead of something like onEvent().

The events should only feature data and not know anything about which systems that may receive it.

Share this post


Link to post
Share on other sites
I'm going to assume you're broadcasting:


class EventVisitor
{
public:
virtual void visit(MouseClickEvent& event) {}
virtual void visit(KeyDownEvent& event) {}
virtual void visit(AwsomeEvent& event) {}
};

class Event
{
public:
virtual void accept(EventVisitor& visitor) = 0;
};

class MouseClickEvent
{
public:
virtual void accept(EventVisitor& visitor) { visitor.visit(*this); }
};

// Etc. for other event classes

// And then for each place you need to handle events, you define a visitor
class SomeEventVisitor: public EventVisitor
{
virtual void visit(MouseClickEvent& event) { /* handle this event */ }
virtual void visit(KeyDownEvent& event) { /* handle that event */ }
};

// And to invoke the event visitor / handler
SomeEventVisitor visitor;
event.accept(visitor);




(but maybe I'm just starting to see the visitor pattern as the hammer and all problems as nails...)

EDIT: Note that the downside of this is that you need a central class (the EventVisitor) that enumerates all your event classes.

[Edited by - Ahnfelt on August 3, 2008 3:30:08 AM]

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!