DIRECTORY Process USING [SetTimeout, DisableTimeout], PrincOpsUtils USING [GlobalFrame], CommFlags USING [doDebug], CommUtilDefs USING [EnableAborts, GetReturnFrame], PupRouterDefs USING [PupRouterForgetAboutSocket, PupRouterKnowAboutSocket, routerLock, PupRouterSocketObject], PupDefs USING [ GetLocalPupAddress, DequeuePup, PupAddress, PupBuffer, PupRouterSendThis, PupSocket, PupSocketID, Pair, PupSocketObject, Tocks, veryLongWait, veryShortWait], BufferDefs, PupTypes; PupSockets: MONITOR LOCKS PupRouterDefs.routerLock IMPORTS Process, PrincOpsUtils, CommUtilDefs, PupRouterDefs, PupDefs EXPORTS PupRouterDefs, PupDefs SHARES BufferDefs = { OPEN PupRouterDefs, PupDefs; InstancePtr: TYPE = POINTER TO FRAME[PupSockets]; free: InstancePtr _ LOOPHOLE[PrincOpsUtils.GlobalFrame[LOOPHOLE[PupSocketMake]]]; GetInstance: ENTRY PROC RETURNS [him: InstancePtr] = { IF free = NIL THEN { him _ NEW PupSockets; START him; -- Do initialization code RETURN; }; him _ free; free _ free.next; }; FreeInstance: ENTRY PROC [him: InstancePtr] = { him.next _ free; free _ him; }; PupSocketMake: PUBLIC SAFE PROC [local: PupSocketID, remote: PupAddress, ticks: Tocks, id: Pair] RETURNS [PupSocket] = TRUSTED { RETURN [PupSocketCommon[GetLocalPupAddress[local, remote], remote, ticks, id]]; }; PupSocketMakeFull: PUBLIC SAFE PROC [local, remote: PupAddress, ticks: Tocks] RETURNS [PupSocket] = TRUSTED { RETURN [PupSocketCommon[local, remote, ticks, [0,0]]]; }; PupSocketCommon: PROC [local, remote: PupAddress, ticks: Tocks, id: Pair] RETURNS [PupSocket] = { him: InstancePtr _ GetInstance[]; him.myPupRouterSocket.local _ local; him.myPupRouterSocket.remote _ remote; him.myPupRouterSocket.id _ id; him.dontWait _ him.kick _ FALSE; PupRouterKnowAboutSocket[@him.myPupRouterSocket]; SELECT ticks FROM veryShortWait => dontWait _ TRUE; veryLongWait => Process.DisableTimeout[@him.myPupRouterSocket.ready]; ENDCASE => Process.SetTimeout[@him.myPupRouterSocket.ready, ticks]; CommUtilDefs.EnableAborts[@him.myPupRouterSocket.ready]; RETURN[him.myPupSocket]; }; PupSocketKick: PUBLIC ENTRY SAFE PROC [s: PupSocket] = TRUSTED { him: InstancePtr _ LOOPHOLE[PrincOpsUtils.GlobalFrame[LOOPHOLE[s.put]]]; him.kick _ TRUE; NOTIFY him.myPupRouterSocket.ready; }; PupSocketDestroy: PUBLIC SAFE PROC [s: PupSocket] = TRUSTED { him: InstancePtr _ LOOPHOLE[PrincOpsUtils.GlobalFrame[LOOPHOLE[s.put]]]; PupRouterForgetAboutSocket[@him.myPupRouterSocket]; FreeInstance[him]; }; Get: ENTRY SAFE PROC RETURNS [b: PupBuffer] = TRUSTED { ENABLE UNWIND => NULL; IF ~dontWait AND myPupRouterSocket.input.length = 0 THEN { IF ~kick THEN WAIT myPupRouterSocket.ready[]; }; kick _ FALSE; IF myPupRouterSocket.input.length = 0 THEN RETURN[NIL]; b _ PupDefs.DequeuePup[myPupRouterSocket.input]; IF CommFlags.doDebug AND b # NIL THEN b.debug _ CommUtilDefs.GetReturnFrame[].accesslink; }; Put: PROC [b: PupBuffer] = { b.dest _ myPupRouterSocket.remote; b.source _ myPupRouterSocket.local; PupRouterSendThis[b]; }; SetRemoteAddress: ENTRY SAFE PROC [a: PupAddress] = TRUSTED { myPupRouterSocket.remote _ a; }; GetLocalAddress: ENTRY SAFE PROC RETURNS [PupAddress] = TRUSTED { RETURN[myPupRouterSocket.local]; }; myPupSocket: PupSocket = NEW[PupSocketObject _ [ put: Put, get: Get, setRemoteAddress: SetRemoteAddress, getLocalAddress: GetLocalAddress] ]; dontWait, kick: BOOL _ FALSE; next: InstancePtr _ NIL; myPupRouterSocket: PupRouterSocketObject; myPupRouterSocket.input _ NEW[BufferDefs.QueueObject]; }. ¦PupSockets.mesa Copyright c 1984 by Xerox Corporation. All rights reserved. HGM March 14, 1981 11:50 AM Andrew Birrell June 22, 1983 5:25 pm Russ Atkinson, October 31, 1984 3:20:13 pm PST Global data. This data should only be referenced by global routines, and not mentioned by local routines. Global routines, exported through PupRouterDefs & PupDefs. These routines manage the various instances. This stuff is a crock, since multiple global frames are poison in a large system. We need to check local to verify that it is valid The following routines are "local" to the global frame instance. They should not refer to global data at all, and should only refer to arguments and per-instance data. The per-instance data. No global routine should discuss these variables without qualifying them. No local routine should discuss them in qualified versions. The initialization is performed for every NEW of the frame. Κ˜codešœ™Kšœ Οmœ1™