PreviousNext

Delegation

An alternative to passing the stack is to treat the stack as a distributed object and pass a reference to it. The server and client would have access to the single stack in the application and the server could use the stack object reference to push and pop elements. A DCE distributed object requires that there be an interface defined for the object and the object implementation be derived from the generated interface class. If the stack being used is supplied by a third party vendor, it may not be possible to modify its definition to derive it from an IDL generated class. The solution is to create a delegate class for the stack to act as an interface to the actual stack object. A delegate class encapsulates the real object and forwards operation invocations to it. The IDL language has been extended to include the ACF attribute cxx_delegate to take advantage of this idiom.

An interface using this attribute will cause the generated interface class to wrap the real object. Only the operations that need to be remote need to be defined in the delegate class interface definition file. The application would then link the delegate server stub with the client. Likewise, the delegate client stub would be linked with the server. The DCE runtime will transparently perform the necessary setup to allow the client application to act as a server for the delegate class. The following example illustrates the use of the cxx_delegate attribute with a Stack class definition:

[ uuid(0ea74f20-e2dc-11ce-9a8e-08002be415b2) ]
interface IStack /* 1 */
{
void push([in] double x); /* 2 */
double pop(); /* 3 */
}

The ACF definition for delegation of the IStack interface is as follows:

[ cxx_delegate(Stack) ] /* 4 */
interface IStack{
include "Stack"; /* 5 */
}

1. An IStack interface is defined

2. The push( ) operation pushes an element onto the encapsulated stack

3. The pop( ) operation pops an element from the encapsulated stack

4. The IStack interface is a delegate for a Stack class

5. Include the Stack.h file into the IDL generated header file

Using the generated server stub and header file from the above IDL fragment, the client application would instantiate an IStack interface pointer and pass it to the remote procedure as follows:

Stack s; // create a local stack object
IStack *iStack; // declare an interface pointer to the local stack
iStack = new IStackMgr(&s); // create the interface ptr
// using the local stack

The cxx_delegate attribute causes the IDL generated classes to be built slightly different than a normal interface class. The interface class contains a constructor that takes a pointer to the delegated class instance as an argument and the manager class supplies complete function bodies. The programmer does not need to supply a manager class for an interface using this attribute.

The server application would use the interface pointer to invoke the push( ) and pop( ) operations on the client's stack instance. The overhead involved is the remoteness of the push( ) and pop( ) operations which are implemented as RPC calls from the server to the client. In this example, the client application would be linked with the IDL generated server stub from the IStack interface and the server application would be linked with the IDL generated client stub from the IStack interface. No extra DCE API calls are required on the part of the client or server stubs. The DCE runtime will handle the necessary overhead to allow the client application to act as a server for the IStack interface.

This idiom is most effectively used when a class type is needed as an RPC argument but the class hierarchy can not be changed by the application or when the overhead of the RPC calls to access the object is outweighed by the combined overhead of converting the object to a network type and the complexity of passing or updating a large amount of data in the RPC call.