Question Deleting a dynamic dataset

KrisM

Member
Suppose i have a demo method that returns a dynamic dataset and that may or may not return an exception.
Code:
block-level on error undo, throw.

class democlass:

    method public void demomethod (output dataset-handle dshDEMO):
    
        define variable doException as logical init yes.
        
        create dataset dshDEMO.
        dshDEMO:read-xmlschema("file", "demo.xsd", false).
        dshDEMO:read-xml("file", "demo.xml", "EMPTY", ?, ?).
        
        if doException
        then undo, throw new Progress.Lang.AppError("Nope!", 101).
        
    end method.
    
end class.

Calling this method may look like this.
Code:
block-level on error undo, throw.

define variable dc as class democlass no-undo.
define variable dsh as handle no-undo.

dc = new democlass().
dc:demomethod(output dataset-handle dsh by-reference).

MESSAGE "no Exception"
    VIEW-AS ALERT-BOX INFORMATION BUTTONS OK.

catch anError as Progress.Lang.Error:
    MESSAGE anError:getMessage(1)
        VIEW-AS ALERT-BOX INFORMATION BUTTONS OK title "Exception".
end catch.

finally:
    delete object dsh.
end finally.

Now when the method does throw an exception the delete object statement in the finally block fails because the dataset-handle is null. The dynamic dataset itself still exists and needs to be cleaned up. What is the proper way to make sure the dynamic dataset gets cleaned up ?
 

Cringer

ProgressTalk.com Moderator
Staff member
I'm pretty sure I would create the dataset in the calling method and pass it as an input-output parameter to the filler method. That way the calling method is responsible for creation and deletion of its objects.
 

Stefan

Well-Known Member
I like to keep clutter to a minimum, so would let the class create the dataset and return the handle instead of a void.
The finally block will need an if valid-handle( dsh ) then before you try to delete the object (you could also add no-error to the delete, but we have a SonarQube rule that flags no-error).

Alternatively, and the more I think about this the more I like it, you could keep a temp-table of dataset handles in your class and clean them up in the destructor. If there is only one dataset at a time then a variable will suffice.
 

KrisM

Member
Thanks for the input.
Changing interfaces is not an option, but adding the destructor in the demo class looks like a working solution.
 

tamhas

ProgressTalk.com Sponsor
"Looks like" is not confidence inspiring. One should "know" what will happen.
 

RealHeavyDude

Well-Known Member
I don't want to play the devil's advocate but I still like the concept of widget pools when using dynamic handle-based objects.

If you don't do anything, by default, all dynamic handle-based objects end up in the unnamed widget-pool of the ABL session. They will remain there even when the procedure or object instance which created them has been destroyed long time ago. This is a recipe for creating memory leaks.

You can easily create an unnamed widget-pool at the beginning of a procedure or use the use-widget-pool to create an unnamed widget-pool that is scoped to the procedure or the class. That way every dynamics handle-based object ends up in that widget-pool which will automatically be deleted when the procedure ends or the class is destroyed.
 

Cringer

ProgressTalk.com Moderator
Staff member
It's a good catch-all, but IMO you should still make the effort to clean up after yourself.
 
Top