DELETE OBJECT statement
- Last Updated: October 8, 2024
- 9 minute read
- OpenEdge
- Version 12.2
- Documentation
Deletes an object such as a widget, a procedure, a server, a socket, or an instance of a class. Deleting the object causes all allocated resources associated with the object to be returned to the system (except when otherwise noted).
Syntax
|
- handle
- A handle to an ABL handle-based object. The handle argument must be a
variable of type HANDLE and must contain a valid handle.
If the handle parameter refers to a widget, the
DELETE OBJECTstatement is a synonym for theDELETE WIDGETstatement.If the handle parameter refers to a persistent procedure handle or proxy procedure handle, the
DELETE OBJECTstatement is a synonym for theDELETE PROCEDUREstatement. This statement deletes a local persistent procedure handle immediately. For a proxy procedure handle, this statement deletes the handle immediately unless there is an outstanding asynchronous request on this handle (handle:ASYNC-REQUEST-COUNTis greater than zero (0)). If handle:ASYNC-REQUEST-COUNTis greater than zero (0), this statement raises theERRORcondition. Otherwise, the statement also sends a request to the application server to delete the corresponding remote persistent procedure on the application server. If the application server is executing any asynchronous requests ahead of it, the AVM queues the delete request (as with any asynchronous remote request) until the application server is available to handle it.Note: This same behavior occurs if the remote procedure deletes itself (usingDELETE...THIS-PROCEDURE) on the application server.If the handle parameter refers to a server handle, the
DELETE OBJECTstatement:- Checks that the handle parameter refers to a valid server handle,
and that the handle parameter's
CONNECTEDattribute is FALSE (no application server is connected to it). If one of these checks fails, the statement raises theERRORcondition. - Deletes the handle immediately, if the server handle is valid,
unless there is an outstanding asynchronous request on this handle (handle
:ASYNC-REQUEST-COUNTis greater than zero (0)). If there is an outstanding asynchronous request, this statement raises theERRORcondition.
Deleting a server handle removes the handle from the server handle chain of the SESSION system handle, and resets
SESSION:FIRST-SERVERandSESSION:LAST-SERVERif necessary. This also deletes all of the asynchronous request handles associated with the server and then deletes the server object.If handle refers to an asynchronous request handle, the
DELETE OBJECTstatement takes one of the following actions:- If the handle
:COMPLETEattribute is FALSE, it raises theERRORcondition. - If the handle
:COMPLETEattribute is TRUE, it removes handle from the chain of asynchronous request handles referenced by theFIRST-ASYNC-REQUESTand theLAST-ASYNC-REQUESTattributes of the server handle, and deletes handle.
If this is a socket handle, the application must disconnect the socket from a port using the
DISCONNECT( )method before a socket object can be deleted. TheDELETE OBJECTstatement raisesERRORif an application deletes a socket object that is still associated with a port.If this is a server socket handle, the application must call
DISABLE-CONNECTIONS( )before a server socket object can be deleted. TheDELETE OBJECTstatement raisesERRORif an application deletes a server socket object that is still listening for connections.Where handle refers to a dynamic buffer, it is recommended practice to execute the
DELETE OBJECTstatement at the same level (that is, as part of the same sub-transaction) as the transaction that created the buffer. - Checks that the handle parameter refers to a valid server handle,
and that the handle parameter's
- object-reference
- An object reference to a class instance. The object reference argument
must be an ABL object reference variable, such as one defined using the DEFINE VARIABLE statement or the DEFINE PARAMETER statement with the
CLASSoption, and it must contain a valid object reference.Note: You can validate an object reference by using the VALID-OBJECT function.When you delete a class instance, the AVM invokes the destructor for the class and the destructor for each class in its inherited class hierarchy, if any. The destructor can be used for freeing resources allocated to the object when the object is deleted. At this time, the object context goes out of scope. In addition, the object is removed from the list of valid ABL class instances (session object chain) referenced by the FIRST-OBJECT attribute or LAST-OBJECT attribute of the SESSION system handle.
If you do not delete a class instance and you have not turned off automatic garbage collection using the No Garbage Collection (
-nogc) startup parameter, the instance is deleted when there are no more references to it.OpenEdge includes a performance tuning feature for ABL class-based applications that controls how the AVM deletes objects. The Re-usable Objects Cache (
-reusableObjects) startup parameter specifies the number of deleted class objects that the AVM stores for later re-initialization. By default,-reusableObjectsis set to 25. When you use-reusableObjects, the AVM transfers the deleted object for most ABL classes to a re-usable objects cache. If your application causes the AVM to instantiate the same class later, the stored object is re-initialized and removed from the cache. The re-initialized object has a new UUID and the same initial data as a new instance of the class. The re-use of the object saves much of the overhead of instantiating a class.Note: The cache does not store .NET classes, .NET-derived ABL classes, classes with static elements, or classes compiled during your session. - NO-ERROR
- The NO-ERROR option is used to prevent the statement from raising
ERRORand displaying error messages.
Notes
- When a temp-table object is passed as a table-handle
output parameter, the deletion of the object following the
DELETE OBJECTstatement is postponed until the procedure goes out of scope. When the procedure returns, the table-handle is created, receives a copy of the original temp-table, and is then returned. - The
OUTPUT TABLE-HANDLEparameter creates a temp-table in the target procedure, which is added to theSESSIONwidget-pool. You must use theDELETE OBJECTstatement to delete this temp-table when it is no longer needed, or you will create a memory leak. - When a dataset-handle parameter is passed
BY-REFERENCE, you are not allowed to delete the dataset object on the caller procedure. If you do, an ERROR is raised (unlessNO-ERRORis specified). - Using automatic garbage collection (the default), the AVM deletes each
class instance when no references to the object exist other than on the session object
chain (accessible using the FIRST-OBJECT attribute or LAST-OBJECT attribute
of the SESSION system handle). When a class
instance is garbage collected, its destructor runs as if you deleted the object using
DELETE OBJECT. As withDELETE OBJECT, automatic garbage collection stores the deleted object in a re-usable object cache. - If you use
DELETE OBJECTon an object reference but there is still another reference to that object, the other reference becomes invalid. Therefore, unless you are sure that the object is no longer needed, it is best to allow garbage collection to delete class-based objects. You just need to be sure that any reference no longer needed is set to the Unknown value (?), or will naturally go out of scope. - Garbage collection does not occur when there is a circular reference (for example,
object A has a reference to object B and object B has a reference to object A). In this
case, a link in the chain needs to be broken in order for garbage collection to free the
objects involved. To break the chain, set one of the references to the Unknown value
(
?) or useDELETE OBJECTon the reference. But again, this is not appropriate if there are other references that need to remain valid.There are other ways to create a circular reference, that do not only involves classes. One case is when a procedure (or class) instantiates a class object that then binds to a temp-table or dataset (via the
BINDoption) in the procedure. In this case, there is circular dependency: the procedure holds a reference to the class instance, and the class instance depends on the temp-table or dataset from the procedure (via theBINDoption). The application code needs to break that circular reference before being able to delete the objects. Another situation that can cause circular references is a class that subscribes to an event in another class, if the class that has the event also has a reference to the class that subscribed to the event. In this case, make sure you unsubscribe from the event when done with it. - You can turn off automatic garbage collection using the No Garbage Collection
(
-nogc) startup parameter. However, if you do so, you must decide when to use this statement to delete each class instance you no longer need. Furthermore, a class instance that has no other references still remains in memory. You must locate it by walking the session object chain and then delete it. - The Re-usable Object Cache (
-reusableObjects) startup parameter controls how many deleted class-based objects are cached. By default, the parameter is set to 25. You can disable this feature by setting the parameter value to zero. When the cache is full and you delete another object, the AVM uses a least-recently used scheme to make room in the cache. - The AVM only uses an object in the re-usable object cache to re-instantiate the same class. It cannot use an object to instantiate another class in the same inheritance hierarchy. For example, Class B inherits Class A and is inherited by Class C. If the cache contains an instance of Class B, the AVM cannot use that object to help instantiate either an instance of Class A or Class C. The AVM can only use that object for a new instance of Class B.
- If you invoke
DELETE OBJECTfrom within a class constructor, specifying the THIS-OBJECT system reference for object-reference, class instantiation stops, and the AVM invokes the destructor for the instantiating class and for each class in its class hierarchy where the constructor has already completed execution. After all destructors have completed, control returns to the statement following the statement that instantiated the class using the NEW function (classes), the NEW statement, or the DYNAMIC-NEW statement. When control returns from the context of aNEWstatement or aDYNAMIC-NEWstatement, the data element set to receive the object reference to the failed class instantiation receives the Unknown value (?). - When you invoke
DELETE OBJECTfrom within a class constructor, the object is stored to the re-usable object cache. By the time the instantiation reaches a constructor, the object data stored in the cache is already in memory. Even though the current instantiation never completes, the AVM can use the object data to instantiate another instance of the class at a later time without problems. - If you need to terminate class instantiation within a constructor,
Progress Software Corporation recommends that you use a
RETURN ERRORor aTHROW(as in the RETURN statement or UNDO statement, respectively). This has the same effect as using theDELETE OBJECT THIS-OBJECTstatement and also raisesERRORon the statement that attempts to instantiate the class. This allows your application to handle the uninstantiated class condition using ABL error handling options, such as the CATCH statement or theNO-ERRORoption on many statements. - For more information on working with socket and server socket objects, see OpenEdge Programming Interfaces.
- For more information on working with class instances, see Develop Object-oriented ABL Applications.
- Automatic garbage collection works for .NET objects, or for ABL objects that derive from .NET objects, similar to how it works for pure ABL class instances. However, .NET objects and the .NET components of an ABL-derived .NET object are also managed separately by .NET garbage collection. Thus, the release of memory held by a .NET object or an ABL-derived .NET object depends on both ABL and .NET garbage collection.
- For a .NET form object, you can typically invoke its
Close( )method or theSystem.Windows.Forms.Application:Exit( )method (for non-modal forms) to both close the form and delete the associated object, making it available for .NET garbage collection. One instance where a form is not deleted using theClose( )method is when a non-modal form is an invisible child form of a multiple-document interface (MDI). In this case, you must also invoke theDELETE OBJECTstatement on the associated object reference, or otherwise remove all references to the form, to make the form available for .NET garbage collection. - In a .NET event handler for the
FormClosingevent, if you do delete object references, do not delete the object reference to the form (sender) that published theFormClosingevent. Otherwise, this causes theFormClosingevent to be published a second time for the same form. If you need to delete the sender of an event associated with the closing of a .NET form, execute theDELETE OBJECTstatement on the sender in an event handler for theFormClosedevent of the form. However, note that with garbage collection, you typically do not need to delete any object references in a .NET event handler. - In ABL, the .NET
Dispose( )method is also available for freeing resources held by a .NET object. Its main purpose is to clean up unmanaged resources, such as file handles or socket connections. A well-behaved object cleans these up in its destructor, but callingDispose( )forces this cleanup in a more timely manner. It is good practice to callDispose( )on any object that implements theIDisposableinterface.Note: .NET automatically callsDispose( )on a non-modal form when it is closed, unless the form is shown as a dialog box. .NET simply hides the dialog when it is closed. However, the AVM callsDispose( )by default for dialogs that inherit fromProgress.Windows.Form. The AVM does not do this if theDisposeDialogOnCloseproperty of the form is set to FALSE. This can be set on a particular instance or globally using the No Dialog Dispose (-nodialogdispose) startup parameter. One use case for not callingDispose( )is if you want to re-use the form at a later time.
See also
DELETE PROCEDURE statement, DELETE WIDGET statement, DESTRUCTOR statement, ERROR-STATUS system handle, THIS-OBJECT system reference, NO-ERROR option, RETURN statement, UNDO statement