The following server code has been distilled from one of the DSOM sample applications provided with SOMobjects Developer Toolkit. It is an example of a server which has an interval timer that signals another server (via DSOM) whenever its timer "pops". Thus, it is both a client (of the server it signals) and a server (because it can receive timer notifications from other servers).
The IDL for the server object class to be used by this server program is as follows. Note that the "noteTimeout" method is oneway, in order to avoid deadlock.
interface PeerServer :SOMDServer { oneway void noteTimeout(in string serverName); // Notification that a timer event occurred in server serverName };
The example server program is outlined as follows. It is assumed that "eman.h" has been included by the program.
MyEMan = SOMEEManNew(); SOM_InitEnvironment(&ev); SOM_InitEnvironment(&peerEv); SOMD_Init(&ev); somPrintf("What is the alias for this server? "); gets(thisServer); SOMD_ImplDefObject = _find_impldef_by_alias(SOMD_ImplRepObject, &ev, thisServer); SOMD_SOMOAObject = SOMOANew(); _impl_is_ready(SOMD_SOMOAObject, &ev, SOMD_ImplDefObject);
void SOMD_RegisterCallback(SOMEEman emanObj, EMRegProc *func); void DSOMEventCallBack (SOMEEvent event, void *eventData) { Environment ev; SOM_InitEnvironment(&ev); _execute_request_loop(SOMD_SOMOAObject, &ev, SOMD_NO_WAIT); } SOMD_RegisterCallback (MyEMan, DSOMEventCallBack);
somPrintf("What is the alias for the target server? "); gets(inbuf); RemotePeer = _somdFindServerByName(SOMD_ObjectMgr, &ev, inbuf);
somPrintf("What is the timer interval, in milliseconds? "); gets(inbuf); Interval = atoi(inbuf);
void TimerEventCallBack (SOMEEvent event, void *eventData) { Environment ev; SOM_InitEnvironment(&ev); /* call the peer, with a oneway message */ _noteTimeout(RemotePeer, &ev, thisServer); } data = SOMEEMRegisterDataNew(); _someClearRegData(data, &ev); _someSetRegDataEventMask(data, &ev, EMTimerEvent, NULL); _someSetRegDataTimerInterval(data, &ev, Interval); somPrintf("Type <Enter> key when ready to go: "); gets(inbuf); regId = _someRegisterProc(MyEMan, &ev, data, TimerEventCallBack, NULL);
Important Do not use someRegister or someRegisterEV to register "callback methods" that would be executed on proxy objects. Instead, write a callback routine that invokes the desired method on the proxy, like the one shown above, and register that routine using the method someRegisterProc.
Note: EMan currently uses the methods someRegister and someRegisterEv to obtain the address of a method-procedure to call when a specified event occurs. If EMan directly calls the method-procedure versus somDispatch, the method call will not be forwarded to the remote object as desired.
_someProcessEvents(MyEMan, &ev);
Before the sample is run, two server implementations should be registered with regimpl. The implementations are identical except for their aliases. One may be called "peerServer1" and the other "peerServer2". The "PeerServer" class should be specified as their server-object class.
Whenever peerServer1's timer pops, the Event Manager causes a method, "noteTimeout", to be sent to the server object in peerServer2. PeerServer2's server object executes this method by displaying a message on its window. Whenever peerServer2's timer pops, a similar sequence occurs with peerServer1. The two servers will run continuously until interrupted.