Skip to main content
GameDev.net gamedev.net
🔒 Locked

RTTI using a look-up table

Started by superpig Jan 19, 2004 at 4:13 AM 7 replies 900+ views
Original Post
superpig
superpig
I was pondering RTTI while drifting off to sleep last night, and had an idea. Existing RTTI methods are meant to be quite slow, I'm told. dynamic_cast has to use the vtable to get the type of the class and compare it to what you're casting, and then cast it if it's allowable. Right? Well, what about using a lookup table for RTTI? On any given object, composed of many base classes, a pointer to one of those base classes will still be somewhere between [OBJECT_BASE_ADDRESS] and [OBJECT_BASE_ADDRESS + size]. So, what if constructors for objects were to store their base addresses in a lookup table, along with a unique ID to represent that class? A 'GetBaseObject' function would then just look for the first pointer which is below the input - perhaps comparing against the upper bound of an object as well, in the event that objects aren't allocated contiguously. You'd use a virtual function - AddRTTIEntry() or something - which base classes override to set their own this pointers and type IDs. Then a downcast becomes something like:
ObjectTypeID GetBaseAddress(const void *in, void *&out);

CMySpecificEntityPtr *mse=0;
CMyBaseEntity *e=someEntity;
if(OBJID_MySpecificEntity == GetBaseObject(e, mse))
{
 //someEntity is actually a MySpecificEntity, so act accordingly
}
  
I believe it's also a little more flexible because you can do things like switching on the return type of GetBaseObject:
void *ent;
switch(GetBaseObject(someEntity, ent))
{
 case OBJID_EntityTypeOne:
  CEntityTypeOne *e = (CEntityTypeOne*)ent;
  e->DoSomething();
  break;
 case OBJID_EntityTypeTwo;
  CEntityTypeTwo *e = (CEntityTypeTwo*)ent;
  e->DoSomethingElse();
  break;
}
  
I *think* it even works fine for multiple inheritance or virtual base classes. But I don't know enough about what goes on under the hood to say. What's this technique like, compared to standard RTTI, for speed and memory usage? Richard "Superpig" Fine - saving pigs from untimely fates, and when he's not doing that, runs The Binary Refinery.
Enginuity1 | Enginuity2 | Enginuity3 | Enginuity4 | Enginuity5 ry. .ibu cy. .y'ybu. .abu ry. dy. "sy. .ubu py. .ebu ry. py. .ibu gy." fy. .ibu ny. .ebu Preserve wildlife: pickle a squirrel today! [edited by - Superpig on January 19, 2004 5:13:51 AM]
Richard "Superpig" Fine - saving pigs from untimely fates - Microsoft DirectX MVP 2006/2007/2008/2009
"Shaders are not meant to do everything. Of course you can try to use it for everything, but it's like playing football using cabbage." - MickeyMouse
Anthony Serrano
Anthony Serrano
Not sure about the performance characteristics of your RTTI scheme, but information on implementing custom RTTI systems can be found in:

Noel Llopis, C++ for Game Programmers, Charles River Media, 2003

and

Scott Wakeling, "Dynamic Type Information", from Game Programming Gems 2, Mark DeLoura, ed., Charles River Media, 2001
superpig
superpig
Something else I realised: it would also be very easy to loop through the table to detect all instances of an object. Say you have a switch that triggers a named door, you could use the table to find all CDoor objects and then check the name on each one.

I''m beginning to wonder if this is the approach that Quake/HL takes...
Richard "Superpig" Fine - saving pigs from untimely fates - Microsoft DirectX MVP 2006/2007/2008/2009
"Shaders are not meant to do everything. Of course you can try to use it for everything, but it's like playing football using cabbage." - MickeyMouse
jesterlecodeur
jesterlecodeur
I''m quite sure it won''t work for multiple inheritance.
If you herit from 2 classes the objet layout will be:

v-table from Class1
members from Class1
v-table from Class2
members from Class2

so when you made a naive cast to Class2 you''ve got a pointer to the Class1 type.

_______________

Jester, studient programmer
The Jester Home in French
_______________
Jester, studient programmerThe Jester Home in French
superpig
superpig
Ah, but the type information you get back from GetBaseAddress should tell you the actual type of the object. Casting it through (Class2*)(UnderlyingType*) should work, because the casts solve the pointer offset problem.

Edit: ah, I think I was slightly missing your point, in that you can only cast to the underlying object instead of to any object that it has inherited from. That's true, but as I demonstrated, you could cast it to the underlying object and then cast it back up to a base class.

[edited by - Superpig on January 19, 2004 7:26:45 AM]
Richard "Superpig" Fine - saving pigs from untimely fates - Microsoft DirectX MVP 2006/2007/2008/2009
"Shaders are not meant to do everything. Of course you can try to use it for everything, but it's like playing football using cabbage." - MickeyMouse
antareus
antareus
Since when is built-in RTTI slow? It''s not as fast as a virtual function call, but that doesn''t automatically promote it to something that should be implemented by the user. Torque supposedly uses it everywhere. I''m just doubting that the RTTI system would be enough of a bottleneck to even be considered. I recall some Effective C++ or More Effective C++ item specifically about RTTI schemes. Stroustrup mentions RTTI is most useful in loosely coupled systems.

I don''t see why anyone would want switches based on types, you get the disadvantages of imperative programming with the disadvantages of OOP. I also think just putting a singleton/global of RTTI types is just like keeping a global around that you can loop through when you need to.

I can understand using this if you wish to have correct and identical object names across compilers however.
--God has paid us the intolerable compliment of loving us, in the deepest, most tragic, most inexorable sense.- C.S. Lewis
zander76
zander76
Hello,

If I am reading this correctly then I think plib (plib.sourceforge.net) does something very similar to this. They use bits to define each class and they have a getType method. Since RTTI was not supported by all compilers they used this method instead. As far as I know there is very little overhead with this.

Ben
Qw3r7yU10p!
Qw3r7yU10p!
In what situations would you be interested in type information?
superpig
superpig
quote:
Original post by petewood
In what situations would you be interested in type information?


Example off the top of my head: collisions. You have collided with an object, but the resultant behaviour would depend on whether that object is ''boiling acid ball'' or ''red rubber ball.''

It allows the objects to be aggregated at a higher level (CCollidable).
Richard "Superpig" Fine - saving pigs from untimely fates - Microsoft DirectX MVP 2006/2007/2008/2009
"Shaders are not meant to do everything. Of course you can try to use it for everything, but it's like playing football using cabbage." - MickeyMouse

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.