Thanks
dark_sylinc. I'm glad you've found some time to share your concerns and those are some strong points, but let's look at them one by one.
dark_sylinc wrote:It's not unique. The same object can be referenced through multiple addresses. This is perfectly valid.
That's only true when virtual inheritance is involved. In other cases it is guaranteed that the object accessed via a typed pointer will always have the same address, e.g. if the scene manager operates on Ogre::Entity* then the one and the same entity will always have the same address even if you have, say, MyEntity that inhertis from Ogre::Entity and MyCoolStuff at the same time. MyCoolStuff* and Entity* values for the same instance of MyEntity will have different values but from the perspective of the scene manager and its clients the Ogre::Entity* values will be unique and consistent.
Virtual inheritance would be problematic but let's be reasonable - the current Ogre's architecture doesn't even allow users to inject Ogre::Entity derivatives of their own. This is strictly controlled by the Ogre::SceneManager implementations. I don't think I will ever see a scene manager with entities or moveables or anything else using virtual inheritance, that's too much overhead even by the modest OOP standards and then there's the movement towards the data oriented design in 2.0! So having this minor restriction on Ogre's internals should be sensible. We're after performance here after all.
Casting pointers to void* and back will be problematic, but that a very bad idea no matter what.
dark_sylinc wrote:Determinism goes to hell. Games relying on determinism no longer are guaranteed to be processed in the same order on each run. Edit: If combined with ordered sets.
That would have been a very good point if Ogre had been a game engine with responsibilities covering managing game objects and their state. Relying on the rendering engine to keep and maintain a deterministic something is rather questionable. Even now it's not really deterministic in some aspects.
dark_sylinc wrote:Correctness: Using a pointer once it has been freed is undefined behavior in C++. Even something innocent-looking as "if( freedPtr != otherValidPtr )" is undefined behavior (not just "*accessing" to it)
Doesn't differ a single bit from a uint handle: "if( freedHandle != otherValidHandle )" is undefined just as well if you like to call it that way.
dark_sylinc wrote:Safety: We're forcing the user to store ptrs instead of handles. While this isn't a problem for advanced users, rookie users have a high chance of still having a ptr copy somewhere in his code after destroying the entity. Having a handle instead is safe and trying to find the entity it is linked to will return null ptr (instead of having a dangling one). Remember, someone has to deal with rookie users in the forum. Granted, they can still make this mistake, but at least we're not encouraging them to.
Well, that's debatable to some extent. The rookie users certainly feel better with named objects and strings, yet the performance hit is severe and we've seen a good deal of support for the idea of switching to something else. Why would you want to impose another hit for requiring the client code too look an entity up instead of using a direct pointer then?
Furthermore, having seen quite a few posts from the rookie users who bumped into that kind of issues I can tell that in 99% cases there will be no big difference, i.e.
Code: Select all
// somewhere deep in the rookie's code
Entity* m_player; // dangling or being other garbage
m_player->setMaterial( m_glowingFire );
a related forum post would be:
rookie wrote:Help, I tried a tutorial with a few changes and I've got "Error: ACCESS_VIOLATION 0xC0000005". What could be the problem?
Now the same scenario with handles:
Code: Select all
// somewhere deep in the rookie's code
Handle m_player; // dangling or being other garbage
m_sceneManager->getEntity( m_player )->setMaterial( m_glowingFire );
a related forum post would be:
rookie wrote:Help, I tried a tutorial with a few changes and I've got "Error: ACCESS_VIOLATION 0xC0000005". What could be the problem?
And having handles would make it super easy for a rookie to pass a handle to a material instead of an entity to the scene manager, unless we have more sophisticated handle types to fight that. That possibility alone would blow up the support forums for good
But even without all that let's keep in mind that v1.7 of Ogre already exposed many methods for dealing with pointers instead of names and then v1.8 pushed that even further. So that tendency was underway already, and for a good reason.
dark_sylinc wrote:Uniqueness, Guaranteed determinism & Correctness while using ptrs would require an extra layer of memory management
I believe I've addressed Uniqueness. It's still not clear what Guaranteed Determinism in the render pipeline pointers could affect negatively if at all. If you have examples please share. I personally question your approach to Correctness but others might not of course. Yet handles are subject to the same flaws in that regard as those you brought up for the pointers.
dark_sylinc wrote:And no, using a handle doesn't mean we need an std::map<int, Entity> at all. We can either:
- Use std::find( vector.begin(), vector.end(), HandleCmp() ); for linear search
- Use vector.insert( std::lower_bound( vector.begin(), vector.end(), HandleCmp() ) ); for having std::set like O(log(n)) search by keeping the vector ordered
Of course, HandleCmp is just a function that compares "arg1->m_id == arg2->m_id"
That would be perfectly legit if the ordered vector were static. But let's consider a scene with entities being added, then temporarily removed, then added back (it's the recommended way to hide entities from the scene btw). How large would the cost of maintaining the ordered vector be then? It would be even larger than for a map! And vectors would suffer from reallocating and copying large amounts of data when the reserved size gets exhausted anyway.
That's not even a tad closer to the performance of an intrusive list if you ask me.