Handling object deletion...

Monkey Forums/Monkey Programming/Handling object deletion...

Brucey(Posted 2011) [#1]
... on targets that support it.

When an instance of my class is no longer required, I'll like it to call a method - like finalize() in Java, ~() in C++ and c#...


But I'm not going to hold my breath :-)


marksibly(Posted 2011) [#2]
Hi,

No finalizers, sorry.

For one thing, as you've noted they're not supported on all targets, but they're also IMO evil.

Here's the main issue: If you have a set of objects that require finalization, what order do you execute finalizers if the objects reference each other?

Since finalizer code can potentially access other objects also due for finalization (via fields), you need to be careful to call their finalizers in such an order that an object's finalizer code does not 'use' (call methods etc) an already finalized object, eg: if Object A references B and both are due for finalization, you need to call A's finalizer first.

But if there are cyclic references, then there may be no correct order and the GC must somehow deal with this.

Hans-boehm GC gets around this by *not* finalizing any such objects - ie: if it detects that a bunch of objects require finalization and are cyclically linked, it wont run any of their finalizers at all. This is IMO the 'correct' solution.

C#/Java (and BlitzMax now) get around this by 'resurrecting' objects that a finalizer can reach that have already been finalized. This is extremely naughty as it means that methods may be called on an already finalized object! It's even possible for a finalizer to permanently resurrect a finalized object by assigning it to a global or something.

In most cases, this doesn't happen - but as I discovered with BlitzMax, it does happen, esp. if you use finalizers a lot. All in all, it's impossible to guarantee 'good' behaviour of finalizers without relying on the programmer to know what's going on.

And of course, all this detection of finalized objects, resurrection etc. is time consuming and adds a lot of complexity.

My advice is to do the complete opposite - if you've got an object that stores an OS resource or something that requires certain cleanup, give it a Close() method and stick it in a map or list to keep it alive.

Since the object MUST be closed by the user, having it 'kept alive' doesn't matter - it can remove itself when Close() is called. But you also get the option to close a whole set of such objects at once by closing all objects in the map.

There's an experimental Resource class in the monkey.resource module that helps with this. It's currently extended by Image and Sound and I will eventually be adding 'DeleteImage', 'DeleteSound', 'DeleteAllImages' and 'DeleteAllSounds' functions. I plan to do the same eventually with files and 'CloseFile' and 'CloseAllFiles'. This worked well in Blitz3D, and I think it'll work well again in Monkey.