Object management system. Streaming, RTTI and object messaging

Started by
9 comments, last by snk_kid 18 years, 7 months ago
I was thinking of an object system for a huge C++ application. Usually in the big engines you have will have one common base class that most objects derive from. The requirements I figure a good object system would have are probably this: o Read/Write objects from memory o Clone itself (that is write obj1 to memory, then create obj2 out of memory) o Identify which object is this objects parent o Identify which object is a child of this object o Uniquely identify itself (UID? GUID?) o Name itself o Determine if obj1 is the same type of obj2 o Determine if obj1.type is derived from obj2.type o Parse a message string and determine which function to call as a result Of course the first thing I'll need is a link to other objects in the system, so a list of children and a pointer to the parent. If multiple inheritance is allowed then I'll need a list of pointers to parents!! Is this something I should hover over or should I forget about multiple inheritance from the beginning? Shoul dI go with virtual functions of all objects, or should I use templates in some way or the other. The system needs to be as easy to set up as possible, I was thinking of templates because I'd like to avoid macros that look like this:

// header file
class SomeClass : Object
{
    DECLARE_OBJECT( SomeClass );
}

// source file
IMPLEMENT_OBJECT( SomeClass );
Where DECLARE_OBJECT would declare the functions inside the class Object and IMPLEMENT_OBJECT would implement them. This would only be for the RTTI based functionality, the streaming in and out would have to be done explicitly by each object. Each object would have to have a GetSize() function that calculates all the sizes of it's member objects and returns the total. The a memory buffer of that size would have to be passed into Object::Save() to store all objects in the memory buffer. An issue I see with streaming is how do I handle small primitive objects? I mean like a Vector or a Matrix? I can't have them derive from the Object base class because that would make them too heavy, and the Object class should obly be used for heap objects. How do I determine which objects should derive from "Object" and which should not. How do I protect against it and make sure the rules are followed? Should I implement a messaging system or not? By messaging system I mean something like this:

Object* obj = new Texture;

obj->sendMessage( "create", --parameter list-- )

class Texture
{
    virtual void sendMessage( msg, --parameter list-- )
    {
        if( msg == "create" )
        {
            // parse the paramter list and call function
            this->create( filename, width, height );
        }
};
How would I have an effective parameter passing mechanism set up. Is a messaging system like this worth it? I'd like to get a discussion going on this. Any past experiences and explanations of systems you are familiar with or techniques that can be used to achive something like this would be great! Thanks in advance.
Advertisement
Just for the record I would like to point out that I personally consider your initial assertion to be complete garbage. Any "huge" system built in that manner would probably suffocate under its own weight and red-tape.

With that said I don't mean to say that the techniques themself are bad used in the correct context to solve a real problem they all serve good purposes, stuffing them into some generic base for the whole project is just crazy though.

You should strive to give each class a clear responsibility and a texture handling messages is, to me conceptually quite far out there.
HardDrop - hard link shell extension."Tread softly because you tread on my dreams" - Yeats
Why you need this ? What is the particular problem you have to solve ?
If you really need this type of architecture you can switch to java for example.
i'm assuming C++ here so,

Quote:Original post by transformation
o Read/Write objects from memory


Non intrusive & intrusive solution boost serialization library

Quote:Original post by transformation
o Clone itself (that is write obj1 to memory, then create obj2 out of memory)


The virtual constructor idiom has it's share of problems and is also intrusive, a cloneable factory is one possible better alternative.

Quote:Original post by transformation
o Identify which object is this objects parent
o Identify which object is a child of this object
o Uniquely identify itself (UID? GUID?)
o Name itself
o Determine if obj1 is the same type of obj2
o Determine if obj1.type is derived from obj2.type


C++ standard already provides a non intrusive RTTI solution that can do all of that (dynamic_cast, std::type_info and operator typeid), don't reinvent squared shaped wheels until you've profiled a need for it.

Quote:Original post by transformation
o Parse a message string and determine which function to call as a result


Possible, whether its a good idea or not depends on the context.

Quote:Original post by transformation
Of course the first thing I'll need is a link to other objects in the system, so a list of children and a pointer to the parent. If multiple inheritance is allowed then I'll need a list of pointers to parents!! Is this something I should hover over or should I forget about multiple inheritance from the beginning?


C++ standard RTTI handles multiple, virtual, and mixed inheritance hierarchies.

Quote:Original post by transformation
Shoul dI go with virtual functions of all objects, or should I use templates in some way or the other.


Depends on the context, you could easily end up using both.

Quote:Original post by transformation
Should I implement a messaging system or not?


Do you have need for interprocess communications? if all you have is internal communications then i would say messaged based system is unnecessary, if you need loosely coupled communication of internal entities then something based on the observer pattern (like boost signals) would be a bettter idea.

On a slightly off topic note, seeing as this all these keeps getting reinvented (with extra bits and pieces added) by game companies all the time even unneccesarily (never bothered profiling, or less knowledgeable about it, or what ever reason), i wont be surprised if C++/CLI will be the dominate language in the games industry in a thew years to come not that its a bad thing mind you [wink].

[Edited by - snk_kid on August 24, 2005 6:29:44 AM]
DigitalDelusions:

I'm sorry for my initial "complete garbage" assertion. I figured these things would be necessary for a distributed system, and even in a non-distributed system would make scripting a breeze. But I havent worked to deep into very many 3d game engines so it was just an "I figure it's like this" kind of statement because the only engine that I have looked into deeply was the WildMagic engine by Dave Eberly and he does have this stuff - but it's toooo intrusive, and lacks a few features.

blizzard999:

No Java... ooh, though since you mention it, is it possible to bind C++ interfaces to Java? because maybe I can do all the networking stuff in Java and the actual interactive stuff in C++ and bind them together somehow? If that's possible, how effective can it be? Is it worth the hassle considering I hate Java and have forced myself to foget everything I learnt in uni about it? Or would it be simpler to stick to what I know?

I wouldn't mind C# though, but then is portability an issue with that? Becuase the application running on a Mac shouldnt even know that the end it's communicating with is uses Windows, everything has to be completely transparent.

snk_kid:

Thanks for pointing me to boost, didn't know there was a serialization library there. Really great!

About RTTI, I always thought that it was like dropping a bombshell on your performance. I'm going to be using RTTI *very* heavily, so from all the things I've heard about the builtin RTTI I thought I'd just build it in myself.

As for the messaging thing, well it's supposed to be a distributed system. But I don't know how copmlicated it can get with this heavy Object base class. I can use an interface to the system so like system1 (s1) will have to go through a standard interface to communicate with s2, but then everything would be hardcoded, the interface would have to know about all the possible object types in the system.

On the other hand if I built in a message system in the Object base class itself, then There's no need for an interface and it will stay an open-closed system. For example one use is that I should be able to query a system for a list of all the running objects it has, there will be no server per-se. And then I need ot be able to ask an object what it can do for me - or actually, I probably won't have to go that far as long as I can query all the objects a system has and as long as I can tell an opbject to do something. So that's the reason for the message passing system.

I've never actually looked at the boost::signals library, I'll check that out now as well. If it's anything like Java RMI then it'll be a big help.

Thanks for your comments.
Quote:About RTTI, I always thought that it was like dropping a bombshell on your performance.


You were mistaken.

I'd use this sort of system for in-game objects, but not for a whole system. If it got really complex, I'd make it a single generic class and implement all special behavior in script.
Personally I like the look of http://sigslot.sourceforge.net/ for the observer pattern stuff. Though people *love* boost around here so I'll probably be strung up suggesting an alternative [wink]
Anything posted is personal opinion which does not in anyway reflect or represent my employer. Any code and opinion is expressed “as is” and used at your own risk – it does not constitute a legal relationship of any kind.
Quote:Original post by transformation
ooh, though since you mention it, is it possible to bind C++ interfaces to Java? because maybe I can do all the networking stuff in Java and the actual interactive stuff in C++ and bind them together somehow? If that's possible, how effective can it be? Is it worth the hassle considering I hate Java and have forced myself to foget everything I learnt in uni about it? Or would it be simpler to stick to what I know?


Yes it's possible but ugly (less ugly with CNI but thats GCJ only) and you don't want to touch java just as much as i do so you would be wasting your time with that. On the other hand you could bind with other languages like Python (Boost.Python helps out alot in the C++ area), Lua etc, etc. You could even use C++/CLI this lets you reuse code from/to any .NET language (J#, C#, F#, VB.NET, etc, etc) with virtually no effort at all the only minor problem with that is C++/CLI standard (currently moderated by MS but not owned by them) is not yet finalized & published although VC++ 8.0 beta 2 has an imp of C++/CLI, i think it will be done somewhere this Sept-Nov.

Quote:Original post by transformation
I wouldn't mind C# though, but then is portability an issue with that? Becuase the application running on a Mac shouldnt even know that the end it's communicating with is uses Windows, everything has to be completely transparent.


C# & .NET itself is portable, its not own by a sole company, its standardized just a spec that a compiler/library vendors can choose to implement (like the Mono project).

Quote:Original post by transformation
About RTTI, I always thought that it was like dropping a bombshell on your performance.


It's a common misconception which is observed/profiled on older popular C++ compilers with not so good C++ standard compliance (the main culprut being VC++ 6.0). The best thing for you to do is use a modern, high standard compliant C++ compiler (which most modern ones are) and profile, don't make assumptions.

Quote:Original post by transformation
I'm going to be using RTTI *very* heavily, so from all the things I've heard about the builtin RTTI I thought I'd just build it in myself.


Using "alot of" RTTI is considered a sign of bad design, try to limit its use. Look into design patterns that help to prevent a need for RTTI, type switching code etc.

Quote:Original post by transformation
I've never actually looked at the boost::signals library, I'll check that out now as well. If it's anything like Java RMI then it'll be a big help.


Its not exactly like RMI although i don't really know much about RMI other than what is says on the tin. Boost.Signals is a signals & slots library, a generic callback framework. It can also be viewed as an implementation of the observer pattern with multiple targets.

Notice how boost gets mentioned alot here, i recommend you do some investigation there, it has close ties with the C++ community & standards committee [grin].
COM's QueryInterface strategy for RTTI is extremely flexible and easy to use. As for cloning an object, why not use the same system you use for serializing? Kill two birds with one stone.
Thanks for the comments again, I'll be stiking with C++ exclusively, though I will have a look at what I can do with C#. boost is at the top of the todo list. I've already gone through the boost::Serialize library and it's perfect as far as I can tell.

I had decided to stick with the built in RTTI, but then I realized that I'll be sending around remote objects in chunks of memory, so I don't think the built in RTTI support can work for objects like that? You can't really determine the object type from a pointer to the objects location in memory can you?

Object* ptr = GetNextObject(stream);if( ptr->type() == cSomeClass::Type ){    // blah...}


Quote:COM's QueryInterface strategy for RTTI is extremely flexible and easy to use. As for cloning an object, why not use the same system you use for serializing? Kill two birds with one stone.


That's what I was thinking of initially. Giving each object some sort of unique identifier, but the problem with that is handling inheritence hierarchies. Can you handle that with COMs QueryInterface as well?

This topic is closed to new replies.

Advertisement