Archived

This topic is now archived and is closed to further replies.

antareus

Cost of dynamic_cast?

Recommended Posts

I have a design that relies on dynamic_cast. The problem is, polymorphism is really only intended for object behavior, not dumb data classes. I pass subclasses of Event around, and individual modules handle certain subclasses of them:
  
//sample of dispatch method

void
ContactList::dispatch(Event* e)
{
	if(StartupEvent* se = dynamic_cast<StartupEvent*>(e))
		OnStartup(se);
	else if(ContactOnlineEvent* e = dynamic_cast<ContactOnlineEvent*>(e))
		OnContactOnline(ce);
	// etc

}
  
Now, I''m anticipating having about ten or fifteen modules in the real world, and lets say each one handles six different types of events. That means there could be up to 90 dynamic_cast attempts for every Event generated, plus the additional cost of virtual function invocation. Am I looking at performance issues? I chose polymorphic Events because I''d like people to be able to write handlers easily and have the luxury of type safety:
  
//sample handler

void
ContactList::OnContactOnline(ContactOnlineEvent* ce)
{
	clistWin.Add(ce->Connection, ce->User);
}
  
Are there any other ways that would be faster or cleaner?

Share this post


Link to post
Share on other sites
quote:
Original post by Magmai Kai Holmlor
How many events per second do you anticipate? If it's less than 100, it's probably a non-issue.

You should say:
How many seconds per event? BTW this is the same design I was talking about in the SE forums, just another part of it.

[edited by - antareus on March 6, 2003 4:35:00 PM]

Share this post


Link to post
Share on other sites
quote:
Original post by antareus
I have a design that relies on dynamic_cast. The problem is, polymorphism is really only intended for object behavior, not dumb data classes.


dynamic_cast, especially when used to "switch" on an object''s type, should be a warning sign. Rather than doing this, why don''t you make you base class have a virtual dispatch method? Then you can call dispatch on an Event*, and the right function gets called.

Share this post


Link to post
Share on other sites
quote:
Original post by sjelkjd
dynamic_cast, especially when used to "switch" on an object''s type, should be a warning sign. Rather than doing this, why don''t you make you base class have a virtual dispatch method? Then you can call dispatch on an Event*, and the right function gets called.



That implies the Events know something about the handlers. I envision an event as a freefloating thing passed around.

A warning sign for what? Event isn''t really an object - its a collection of named fields, some of which are common to all events.

If I went ahead and made a dispatch method for events, then that implies that:
a. Events know about the components which they live under. More coupling. Components already know about events, so this is now a circular dependency.
b. Events know how to ''execute'' themselves, which is somewhat troubling in my mind. More importantly if I have n number of events, every component now has n vtable entries.
c. It doesn''t let user classes make their own events, since the handlers are essentially hardcoded.

Share this post


Link to post
Share on other sites
RE the warning part - not a warning in your program, but a warning to the coder that there might be a better way.

It sounds like what you want is multiple dispatch(functions virtual on more than one type). How extensible is this system? Do you want users to define their own events?

You might want to check out more effective c++ by scott meyers, or modern c++ design by alexandrescu, for information on multiple dispatch.

Share this post


Link to post
Share on other sites
here is kind of a hacky way of doing it:


// possibly in another header to prevent circular dependancy
#define STARTUP_ID 0
#define CONTACT_ONLINE_EVENT_ID 1
...

...
void ContactList::dispatch(Event * e)
{
int Event = e->GetEvent();
if(Event == STARTUP_ID)
{
StartupEvent * se = dynamic_cast(e);
OnStartup(se);
}
else if(Event == CONTACT_ONLINE_EVENT_ID)
{
ContactOnlineEvent * cone = dynamic_cast(e);
OnContactOnline(cone)
}
//...
}


in your Event base class, have a virtual int GetEvent();, and in each event type have it return its type.

its not that good of a solution though, just giving a way to get rid of the dynamic cast crazyness.

Share this post


Link to post
Share on other sites
quote:
Original post by sjelkjd
RE the warning part - not a warning in your program, but a warning to the coder that there might be a better way.


Right. I was saying that I don''t see an Event as a full-fledged object, so why subject it to the same standards that objects are held up against?

quote:
It sounds like what you want is multiple dispatch(functions virtual on more than one type). How extensible is this system? Do you want users to define their own events?

They should be able to if they can conceive of new ones, then they can write a downstream component to catch the event they generated and do something with it.

quote:
You might want to check out more effective c++ by scott meyers, or modern c++ design by alexandrescu, for information on multiple dispatch.

Multiple dispatch is exactly what I want. I''ve read some of More Effective C++ but can''t remember specific mentions of it. I''m looking at the Visitor pattern in the GoF book and it does not seem applicable. As far as I can tell any multiple dispatch setup requires you to define loads of virtual functions for each and every event type, 90% of which won''t even be used most of the time.

Someone else suggested registering handlers by the string representation of the derived Event class and then using typeid on the incoming events to get the handler chain for it which is pretty damn slick.

Share this post


Link to post
Share on other sites