PreviousNext

Implementing Distributed-Dynamic Objects

After the server has been initialized and is listening for calls, one obvious question arises: How does the server create distributed objects? The server creates objects locally, just as they are created in typical C++ applications, by allocating variables of the class types or by dynamically creating them with the C++ new operator, as shown in the following example:

// m1 is allocated as a variable of class Matrix Matrix m1;
// m2 is a pointer variable of class Matrix allocated with "new"
Matrix *m2 = new MatrixMgr(0, 0, 0, 0);

However, clients have no way to use these objects since they are only local and not yet available as distributed objects.

For distributed dynamic objects, the server needs a way to know when a client requests that the server create a dynamic object. This is done by using an ACF to associate an appropriate interface operation with the server's implemented manager class. You must then write manager code that turns server-local objects into distributed dynamic objects.

When you compile the interface definition file to create the interface header file and server stub, you use an ACF to customize how your application code uses the interface, as shown in the following:

/* FILE NAME: matrix.acf */
/* This file defines some attributes for the Matrix interface */
interface Matrix {
/* include header files generated into the server stub */
[sstub] include "matrix_mgr";

/* createMatrix should be mapped as a creator function. */
/* The MatrixMgr is a class derived from the interface class. */
[cxx_new(MatrixMgr)] createMatrix();
.
.
.

[sstub] include
Use the include statement with the sstub attribute to make the IDL compiler include specific header files in the server stub. In this example, this is required so that the stub has a declaration of the manager class.

[cxx_new(MatrixMgr)] createMatrix( );
Use the cxx_new attribute with the name of the implemented manager class (MatrixMgr) as an argument, and apply it to the interface operation that is intended to create a dynamic object, createMatrix. The manager class can be the idl-generated one, as in this example, or it can be one you derived from the generated manager class.

The following C++ code shows examples of constructor and destructor functions you write for the manager class (MatrixMgr):

.
.
.
// Constructor
MatrixMgr::MatrixMgr(idl_long_int v1, idl_long_int v2,
idl_long_int v3, idl_long_int v4)
{
d[0][0] = v1;
d[0][1] = v2;
d[1][0] = v3;
d[1][1] = v4;
}

// Destructor for a 2x2 Matrix.
// In this application, the destructor does nothing.
MatrixMgr::~MatrixMgr(void)
{
return;
}

MatrixMgr::MatrixMgr
In the trivial case, a constructor automatically initializes the object allocated by the C++ new operator. For this application, the constructor simply fills in the data structure with the values sent in the remote procedure call. In more realistic applications, the C++ constructor may have to perform additional work. C++ allows you to define constructor functions that contain application-specific code that is automatically called immediately after the object is created.

MatrixMgr::~MatrixMgr
In addition to a constructor, C++ allows you to define destructor code that is called to do application-specific cleanup just prior to the release of storage for the object. In this example, the destructor is a dummy function that has no special code and does nothing.

When a client initiates the creation of a dynamic object, the server receives a remote procedure call request for the createMatrix function. This causes the server stub to call the C++ constructor for the specified manager class (in this example MatrixMgr), which creates a new object on the server. When this happens, the DCE runtime stores information about the object in a table that also associates the object with the requesting client. No other clients have access to a dynamic object unless the originating client gives an object reference to another client. The runtime uses reference counting to keep track of how many clients know about the object. When a client deletes the object, the reference count on the server is reduced. The object on the server is deleted only when the reference count reaches zero, which indicates that there are no more clients with references to the object.