Friday, September 19, 2008

Freaking pointers

Recently I had some serious issues with cross referencing of pointed objects.
Normally in a 3D engine there isn't much trouble with pointers until those objects start to be shared with an application that may put them in a list for a user to select them or, even worse, delete them.

With little, or no design behind the tool/editor portion of things (the tool/editor part is only meant for quick debugging and testing), things got pretty messy.
Because the final product will not allow editing and single object's deletion, I tried to patch things up by using more and more smart pointers.
I built my own intrusive reference counted pointers, with some trouble, but working fine overall. I eventually switched to boost's intrusive_ptr.. because I suspected some issues and it's very hard to get those things 100% right. Smart pointers are a bit like writing a portion of a programming language. Things at those levels should be very reliable !

So, I coded my way to complete smartpointerdom and then started reversing 8)

One thing is sure, cross referenced objects in application programming are a big beast that one shouldn't undertake without proper design.
I must admit that I'm not really fluent at this. I mean, I don't really have a tried and true way of writing clean code that will not get caught into recursive double-suicides of objects.
I guess that the problem really is that I wish I'd have to put less thought into those issues, because I'm not really in the business of writing an application.
Quick fixes like using smart pointers will save one from mad crashes, but poor design will still leave dangling objects here and there, user interfaces keeping a lock on a 3D model which was meant to be deleted but it's still alive somewhere.

One solution I found for higher level interfaces is to use strings to refer to objects.
For example I have a scene system where there are only a few of camera shots, which I will address them like PlayShot( "Shot 2" ).
The commands to execute are so few that I can run them by a script (LUA) and I can name elements with plain strings.
Then, one may end up trying to use deleted objects, but because references are loose, addressing a non-existent object will only produce a failed attempt, not a crash (though by a quick series of events one may end up referencing a wrong object that accidentally borrowed the name of a previously existing object ! (naming by generated unique IDs would solve this)).

The more proper way of doing things however is to establish proper references, ownerships and proper communication channels.
So, if the animation manipulation interface wants to use a 3D model or an animation sequence, it must also provide a communication channel (a call-back, virtual method, event system) to be told when the object is altered or deleted.

Of course, the first thing is to keep things simple: does one really need the option to delete a single object at any time ? Or could one settle for a FreeAll() that resets all things at once ?

..I have no time to build a proper object reference communication infrastructure kind of thing, so for now I'm optiming for a simple FreeAll() 8)
Still using reference counted smart pointers in some cases (textures and geometries in the engine), but I'm trying to avoid overusing them as a quick solution. No quick solution in C++...