OE116
I wounder how the cleanup is done, or if it is done when doing the following code:
If the class has a def temp-table ... etc.
def var oClass as class myClass().
do i = 1 to 100:
oClass = new myClass().
:
:
end.
delete object oClass.
Will the delete fix all of them, or do I have to handle this different? and if so, how?
//Geir Otto
|
|
Garbage collection will "probably fix it", but..
I prefer to DELETE whatever I CREATE, so:
do i=1 to 100 ON ERROR UNDO, THROW:
oClass = new myClass().
.
.
FINALLY:
DELETE OBJECT oClass.
END.
end.
My recommendation:
- Delete everything you create
- Delete nothing
anything in between is confusing.
David.
|
[quote user="Mike Fechner"]
[/quote]
The docs specifically state there is no guarantee they'll be deleted in any particular order - if your code depends on order of deletion the application has to do it explicitly.
|
Documentation … and reality ;-) the ABL GC works synchronously. Reference gone. Object gone.
Right now that's true, and will be true until PSC decides to change the GC algorithm to something else. There are already requests in the works for changes like deferring all object deletions until the end of an appserver call for performance reasons.
Thanks, all, I hoped that was the way it worked.
I would recommend against explicitly deleting objects using the delete object statement.
In your case each iteration of the loop will cause the reference to the previous object to be overwritten with the new one, causing it to get garbage collected (when the actual collection occurs should not concern you).
Only the last iteration's object will stay around for as long as there's a reference to it. If the variable that references it goes out of scope, that object will also be release and eventually garbage collected.
For global variables (or similar) just set them to ? to clear the reference and let the garbage collector do its work.
That is like recommending to leave your house door wide open, for the garbage collector guy to pick up the garbage for you. It may sound like a "comfortable" idea, but I will never suggest that.
It's truly very optimistic. You will never really know how many references there are to an object, unless you fully control the class implementation, which is never true for most systems.
References to an object are not only the variables where you initially store the object, but also any reference another object may have to it. Can you be sure about what happens to an object that PUBLISH and it's explicit reference is lost? I don't, I won't bet on it, it may change at any moment, as none of us controls garbage collector implementation.
So what do you recommend to do a controlled garbage collection?
I always recommend to explicitly delete objects that you don't longer need. That not only ensures there are no "hanging around objects" but also helps others understand the code.
Think about another programmer looking at the code:
- The object is not deleted because is garbage collected
- The object is not deleted because is used somewhere else
- The object is not deleted because is internally referenced by global objects
You should document that, it's a lot easier to just delete the object. Explicitly deleting objects has no drawbacks, not doing so does.
Garbage collection is a great feature but should not be used as a "programming practice" because it may bite you harder than you can imagine, and if that happens the only solution will be to go back to the code and add all the "missing deletes".
In your original example, adding a FINALLY block where you DELETE the object, is more than enough, and puts your intentions very clearly. My first thinking of your example was that you created 100 objects to do a "parallel" sort of stuff with all of them, only because there was no DELETE statement.. (yes, I know I'm weird..)
I’m definitively with David on this… and I do hate the ‘dispose (anti) pattern’ as well, mind you even in 4GL there are ‘unmanaged resources’ that you need to clean yourself as won’t be handled by the GC (sockets, com handles, sax/x-document, etc).
|
I recently had this bite me in production - a Progress-supplied class had something going on under the covers that prevented it from getting GC'd, and it didn't get caught until it got to production.
DELETE OBJECT never harms and can save you from production related excitement.
Normally, I would agree with both David and Marian. However, the Progress OO manual states:
"Progress Software Corporation recommends that you allow garbage collection to delete
class-based objects whose reference counts are 0."
Take that as you will...
And who’s stoping the GC to ‘delete class-based object whose references counts are 0’? I certainly don’t do anything of that kind, you’re just trying to put me on the naughty list? :)
Ask Julian how he learned about the bidirection linkages that result from using publish/subscribe eventually leading to an out-of-memory condition...
Coming from the Progress Software Corporation side, I would say that the recommendation to use garbage collection is a simplification. There are advantages/disadvantages on both sides:
* There is nothing wrong with doing DELETE OBJECT if you are sure that the object is not being used anywhere. If it is not a straight-forward scenario and thus you are not sure, it's better to let garbage collection take care of it.
* The AVM does not garbage delete an object when it is part of a circular reference. For those cases, you may want to use DELETE OBJECT (the other way is to break the circle by clearing one or more references). This usually comes up with Forms and and classes that use event subscriptions. Though again, when you do it, you have to be sure that you are not deleting something that is being used.
In the example that started all this, with doing NEW in a loop and assigning the new class reference into the same variable each time, there is no ambiguity. Garbage collection will handle this just fine and there is no need whatsoever for DELETE OBJECT. And for the same reason, there is no problem if you do use DELETE OBJECT. So take your pick.