DataSnap 2009 Memory Management

By: Steven Shaughnessy

Abstract: Memory management conventions used for server class instances, server method parameters and return values.

For natively compiled DataSnap servers and clients the memory of objects used for server class instances, server method parameters and return values must be freed. This article documents when these objects are automatically freed by DataSnap and when these objects need to be freed by the application.

    Server class instances

By default, the TDSServerClass LifeCycle property controls the creation and destruction of server class instances. Currently there are three possible settings for the LifeCycle property: TDSLifeCycle.Server, TDSLifeCycle.Session, and TDSLifeCycle.Invocation.

A lifecycle of TDSLifeCycle.Server causes all clients to share a single server class instance. This is effectively a singleton. Since a single instance can be shared across multiple threads, the application must provide thread safe access to fields of the server class as needed. TDSLifeCycle.Server lifecycle objects are created the first time one of its methods are called and destroyed when the server is stopped.

A Lifecycle of TDSLifeCycle.Session causes each client connection to have its own server class instance. TDSLifeCycle.Session lifecycle objets are created the first time one of its methods are invoked. They are destroyed when the owning connection is closed.

A Lifecycle of TDSLifeCycle.Invocation causes each invocation of a server method to have a new server class instance created for every invocation of one of its server methods. They are destroyed after the method invocation is complete and all out and return parameters have been received by the client.

If a server class inherits from TComponent, the TComponent.Create(AOwner: TComponent) constructor will be called with a nil constructor to create instances of that server class. Otherwise the constructor with no parameters will be used to create instances.

The creation and destruction of server class instances can be overridden by wiring the TDSServerClass OnCreateInstance and OnDestroyInstance events. This allows customized constructors to be used for constructing a server class instance. It is also useful for implementing an object pool when the TDSLifeCycle.Invocation lifecycle setting is in use.

    Server method parameters and return values

Client convention

By default, the DataSnap driver, client proxy classes and the VCL take responsibility for freeing input, output, and return parameter objects. These objects are feed when ever the underlying server method is executed, closed or freed. One exception is that TDataSet or TParams instances that have a non-nil owner will not be automatically freed since it is assumed their owner is managing the life time of these allocations.

Overriding client memory ownership

For the VCL calling the methods below with AInstanceOnwer set to false prevents these objects from being automatically freed:

procedure TParam.SetDataSet(Dataset: TDataSet; AInstanceOwner: Boolean);
procedure TParam.SetParams(Params: TParams; AInstanceOwner: Boolean);
procedure TParam.SetStream(Stream: TStream; AInstanceOwner: Boolean);

Typically these properties will be used by applications instead which cause the objects to be freed automatically (Except for objects that have a non-nil owner):

TParam.ASDataSet
TParam.AsParams
TParam.ASStream

For the dbExpress Driver framework calling the methods below with AInstanceOnwer set to false prevents these objects from being automatically freed:

procedure TDBXWritableValue.SetDBXReader(const Value: TDBXReader; const AInstanceOwner: Boolean);
procedure TDBXWritableValue.SetStream(const Stream: TStream; const AInstanceOwner: Boolean);

function TDBXValue.GetStream(AInstanceOwner: Boolean): TStream;
function TDBXValue.GetDBXReader(AInstanceOwner: Boolean): TDBXReader;

The client proxies generated from the context menu of the TSQLConnection component or by calling DSProxyGen.exe have two constructors. The constructor below can be used to keep the proxy class from automatically freeing parameters:

Create(ADBXConnection: TDBXConnection; AInstanceOwner: Boolean);

    Server convention

By default, server method input, output and return parameters are all freed by DataSnap when no longer needed. One exception is that TDataSet or TParams instances that have a non-nil owner will not be automatically freed since it is assumed their owner is managing the life time of these allocations.

This behavior can be overridden by returning wrapper objects. In this case the wrapper object will be freed, but the wrapper object can decide in its destructor implementation whether to free the object it is wrapping. Currently there are wrapper objects provided for the TDataSet and TParam classes. These wrapper classes are included in the DBXDBReaders unit. The TDataSet wrapper is called TDBXDataSetReader. The TParams wrapper is called TDBXParamsReader. The constructor of these wrapper objects takes a boolean “InstanceOwner” parameter. If the InstanceOwner is false, the wrapper object will not free the wrapped object when it is freed by DataSnap.

Server Response from: ETNASC04