The preceding program has been rewritten below showing how DSOM can be used to create and access a "Stack" object somewhere in the system. The exact location of the object does not matter to the application; it just wants a "Stack" object. Note that the stack operations of the two programs are identical. The main differences lie in stack creation and destruction, as highlighted below. (Also see "Memory management" later for more information on allocating and freeing memory.)
#include <somd.h> #include <stack.h> int main(int argc, char *argv]) { Environment ev; Stack stk; long num = 100; SOM_InitEnvironment(&ev); SOMD_Init(&ev);
/* The StackNewClass invocation is optional and unnecessary * in the client program when the class object is created in * the SOMInitModule function that is invoked during DLL * initialization. */ StackNewClass (Stack_MajorVersion, Stack_MinorVersion); stk = _somdNewObject(SOMD_ObjectMgr, &ev, "Stack", ""); /* Verify successful object creation */ if ( OperationOK(&ev) ) { while ( !_full(stk, &ev) ) { _push(stk, &ev, num); somPrintf("Top: %d\n", _top(stk, &ev)); num += 100; } /* Test stack overflow exception */ _push(stk, &ev, num); OperationOK(&ev); while ( !_empty(stk, &ev) ) { somPrintf("Pop: %d\n", _pop(stk, &ev)); } /* Test stack underflow exception */ somPrintf("Top Underflow: %d\n", _top(stk, &ev)); OperationOK(&ev); somPrintf("Pop Underflow: %d\n", _pop(stk, &ev)); OperationOK(&ev); _push(stk, &ev, -10000); somPrintf("Top: %d\n", _top(stk, &ev)); somPrintf("Pop: %d\n", _top(stk, &ev)); _somdDestroyObject(SOMD_ObjectMgr, &ev, stk); if ( OperationOK(&ev) ) { somPrintf("Stack test successfully completed.\n"); } } SOMD_Uninit(&ev); SOM_UninitEnvironment(&ev); return(0); }
boolean OperationOK(Environment *ev) { char *exID; switch (ev->_major) { case SYSTEM_EXCEPTION: exID = somExceptionId(ev); somPrintf("System exception: %s\n", exID); somdExceptionFree(ev); return (FALSE); case USER_EXCEPTION: exID = somExceptionId(ev); somPrintf("User exception: %s\n", exID); somdExceptionFree(ev); return (FALSE); case NO_EXCEPTION: return (TRUE); default: somPrintf("Invalid exception type in Environment.\n"); somdExceptionFree(ev); return (FALSE); } }
Let's step through the differences.
First, every DSOM program must include the file <somd.h> (when using C ++, <somd.xh>). This file defines constants, global variables, and run-time interfaces used by DSOM. Usually, this file is sufficient to establish all necessary DSOM definitions.
Next, DSOM requires its own initialization call.
SOMD_Init(&ev);
The call to SOMD_Init initializes the DSOM run-time environment SOMD_Init must be called before any DSOM run-time calls are made. A side effect of calling SOMD_Init is that a run-time object, called the DSOM Object Manager, is created, and a pointer to it is stored in the global variable, SOMD_ObjectMgr, for programming convenience. The DSOM Object Manager provides basic run-time support for clients to find, create, destroy, and identify objects. The Object Manager is discussed in detail in the section entitled "Basic Client Programming."
Next, the local stack creation statement,
stk = StackNew();was replaced by
stk = _somdNewObject(SOMD_ObjectMgr, &ev, "Stack", "");
The call to somdNewObject asks the DSOM Object Manager (SOMD_ObjectMgr) to create a "Stack" object, wherever it can find an implementation of "Stack". (There are other methods with which one can request specific servers.) If no object could be created, NULL is returned, and an exception is raised. Otherwise, the object returned is a "Stack" proxy.
Note: On AIX, the following call may be needed before the somdNewObject call, if the "Stack" class implementation has been linked directly with the program executable (vs. using a dynamic link library, or DLL). This call will properly initialize the class for use by DSOM (this initialization is done in SOMInitModulefor DLLs):
StackNewClass(Stack_MajorVersion, Stack_MinorVersion);
A proxy is an object that is a local representative for a remote target object. A proxy inherits the target object's interface, so it responds to the same methods. Operations invoked on the proxy are not executed locally, but are forwarded to the "real" target object for execution. The client program always has a proxy for each remote target object on which it operates.
From this point on, the client program treats the "Stack" proxy exactly as it would treat a local "Stack". The "Stack" proxy takes responsibility for forwarding requests to, and yielding results from, the remote "Stack". For example,
_push(stk,&ev,num);
causes a message representing the method call to be sent to the server process containing the remote object. The DSOM run-time in the server process decodes the message and invokes the method on the target object. The result (in this case, just an indication of completion) is then returned to the client process in a message. The DSOM run time in the client process decodes the result message and returns any result data to the caller.
At the end of the original client program, the local "Stack" was destroyed by the statement,
_somFree(stk);
whereas, in the client program above, the "Stack" proxy and the remote "Stack" are destroyed by the statement,
_somdDestroyObject(SOMD_ObjectMgr, &ev, stk);
If the client only wants to release its use of the remote object (freeing the proxy) without destroying the remote object, it can call the somdReleaseObject method instead of somdDestroyObject.
Finally, the client must shut down DSOM, so that any operating system resources acquired by DSOM for communications or process management can be returned:
SOMD_Uninit(&ev);This call must be made at the end of every DSOM program.