DIRECTORY YggEnvironment, YggImport, YggTransMgr, YggConversationTable, YggCoordinator, YggCoordinatorInternal, YggDummyProcess, YggDummyRPC; YggCoordinatorRemoteCallsImpl: CEDAR MONITOR IMPORTS YggDummyProcess EXPORTS YggCoordinatorInternal = BEGIN Conversation: TYPE = YggEnvironment.Conversation; TransID: TYPE = YggEnvironment.TransID; nProcessesCalling: INT _ 0; maxProcessesCalling: INT = 20; nProcessesIdle: INT _ 0; maxProcessesIdle: INT = 10; parmsTaken: CONDITION; parmsArrived: CONDITION; Parms: TYPE = YggCoordinatorInternal.Parms; parms: Parms; parmsOccupied: BOOL _ FALSE; Results: TYPE = YggCoordinator.Results; timesCalledPassParms: INT _ 0; timesWaitedOnParmsTaken: INT _ 0; PassParms: PUBLIC ENTRY PROC [p: Parms] = { ENABLE UNWIND => NULL; timesCalledPassParms _ timesCalledPassParms + 1; WHILE parmsOccupied DO timesWaitedOnParmsTaken _ timesWaitedOnParmsTaken + 1; WAIT parmsTaken; ENDLOOP; parms _ p; parmsOccupied _ TRUE; IF nProcessesIdle > 0 THEN NOTIFY parmsArrived ELSE IF nProcessesCalling < maxProcessesCalling THEN { nProcessesCalling _ nProcessesCalling + 1; TRUSTED {YggDummyProcess.Detach[FORK CallerProcess[]];}; }; }; CallerProcess: PROC [] = { alpineTransMgr: REF _ NIL; }; GetParms: ENTRY PROC [parmsPtr: --RESULT--POINTER TO Parms] = INLINE { ENABLE UNWIND => nProcessesIdle _ nProcessesIdle - 1; nProcessesCalling _ nProcessesCalling - 1; WHILE NOT parmsOccupied DO IF nProcessesIdle = maxProcessesIdle THEN RETURN WITH ERROR Stop; nProcessesIdle _ nProcessesIdle + 1; WAIT parmsArrived; nProcessesIdle _ nProcessesIdle - 1; ENDLOOP; TRUSTED {parmsPtr^ _ parms;}; parmsOccupied _ FALSE; nProcessesCalling _ nProcessesCalling + 1; NOTIFY parmsTaken; }; Stop: ERROR = CODE; TRUSTED { YggDummyProcess.DisableTimeout[@parmsTaken]; YggDummyProcess.EnableAborts[@parmsTaken]; YggDummyProcess.DisableTimeout[@parmsArrived]; YggDummyProcess.EnableAborts[@parmsArrived]; }; END. pYggCoordinatorRemoteCallsImpl.mesa Copyright Σ 1985, 1988 by Xerox Corporation. All rights reserved. Makes YggTransMgr calls using a pool of processes. Enforces a bound on the number of processes devoted to YggTransMgr calls. Last edited by MBrown on November 21, 1982 3:40 pm Hauser, March 28, 1985 9:48:22 am PST Bob Hagmann May 2, 1988 2:29:54 pm PDT NOTES: We land in debugger if AlpineCoordinatorAndWorker.Prepare or .Finish raises Refused[wrongCoordinator]. Also if YggDummyRPC.CallFailed[protocolError] is raised. YggImport, number of processes engaged in remote calls. number of processes waiting on parmsArrived condition. A process calling PassParms waits here if parms is occupied on entry. A process calling GetParms waits here if parms is empty on entry. If parmsOccupied, then parms is meaningful. Statistics on module usage: Returns from the procs PassParms and GetParms below are strictly interleaved, due to the single-element parms buffer. This proc has had the RPC calls commented out A caller process is outside the monitor except while calling GetParms. parms: Parms; conversation: YggDummyRPC.Conversation; alpineTransMgr: AlpineTransMgrRpcControl.InterfaceRecord; whyCallFailed: YggDummyRPC.CallFailure; result: Results; DO TRUSTED {GetParms[@parms ! Stop => GOTO stop];}; conversation _ YggConversationTable.Fetch[parms.w.first.worker]; alpineTransMgr _ YggImport.GetTransMgrInterface[parms.w.first.worker]; IF conversation = NIL OR alpineTransMgr = NIL THEN { result _ [bindingFailed, none[]]; } ELSE { ENABLE { YggDummyRPC.CallFailed => CHECKED { whyCallFailed _ why; GOTO callFailed }; alpineTransMgr.Refused => { }; }; SELECT parms.proc FROM prepare => { state: YggEnvironment.WorkerState _ alpineTransMgr.WorkerPrepare[ conversation, parms.c.transID, parms.newTrans]; result _ [none, prepare[state]]; }; finish => { alpineTransMgr.WorkerFinish[conversation, parms.c.transID, parms.requiredOutcome]; result _ [none, finish[]]; }; ENDCASE => ERROR; EXITS callFailed => { SELECT whyCallFailed FROM timeout, unbound => { parms.w.first.worker.TransMgrInterfaceCallFailed[alpineTransMgr]; result _ [callFailed, none[]] }; busy => result _ [busy, none[]]; runtimeProtocol, stubProtocol => ERROR; ENDCASE => ERROR; }; }; alpineTransMgr _ NIL; YggCoordinatorInternal.ReturnResults[parms.c, parms.w, result]; ENDLOOP; EXITS stop => RETURN ! Stop -> calling process should die. Pass a POINTER TO Parms instead of returning Parms, to avoid warnings about potentially unsafe long REF-containing return record. no call to make and already enough idle processes, so terminate process. Hauser, March 7, 1985 2:47:02 pm PST Nodified, added copyright. Κ•˜šœ"™"IcodešœB™B—Jšœ2™2JšœI™Išœ™Jšœ#™#K™%K™&—J˜J˜Jšœ™J˜JšœK™KJšœT™TJ˜˜šΟk ˜ J˜J˜ J˜ J˜J˜J˜Jšœ˜Jš œ˜ J˜——šœ ˜,š˜J™ Jšœ˜—š˜J˜—Jšœ˜J˜Jšœœ˜1Jšœ œ˜'J˜šœœ˜Jšœ,™,—Jšœœ˜šœœ˜Jšœ6™6—Jšœœ˜J˜šœ  œ˜JšœE™E—šœ œ˜JšœA™AJ˜—Jšœœ ˜+J˜ šœœœ˜Jšœ+™+—Jšœ œ˜'J˜Jšœ™Jšœœ˜Jšœœ˜!J˜J˜JšœT™TJšœ ™ J˜šΟn œœœœ˜+Jšœœœ˜J˜0šœ˜J˜6Jšœ ˜Jšœ˜—J˜ Jšœœ˜Jšœœœ ˜.šœœ)œ˜6J˜*Jšœ œ˜8J˜—J˜J˜—J™-šž œœ˜JšœF™FJ™ Jšœ œ™'J˜J™9Jšœ'™'J™š™Jšœ#œ ™0J™@J™Fš œœœœœ™4J™!J™—šœ™šœ™Jšœœœ™KJ™J™—šœ ™™ ™AJ™/—J™ J™—™ J™RJ™J™—Jšœœ™—š™™šœ™™J™AJ™ —J™ Jšœ!œ™'Jšœœ™—J™——J™—Jšœœ™J™?Jšœ™—š™Jšœ™—J˜J˜—š žœœœ Οc œœ œ˜FJšœ%™%JšœK™KJšœ5™5Jšœœ(˜5J˜*šœœ˜šœ#˜)JšœH™HJšœœœ˜—J˜$Jšœ˜J˜$Jšœ˜—J˜Jšœœ˜J˜*Jšœ ˜J˜J˜—Jšœœœ˜J˜šœ˜ Jšœ,˜,Jšœ*˜*Jšœ.˜.Jšœ,˜,J˜—J˜Jšœ˜—™$K™—K™—…—Š