<> <> DIRECTORY BridgeExec USING [CreateProc, DestroyProc, Instance], IO USING [STREAM], Process USING [Detach], RefTab USING [Create, Delete, EachPairAction, Fetch, Pairs, Ref, Store], Rope USING [ROPE], SymTab USING [Create, Delete, Fetch, Ref, Store]; BridgeExecImpl: CEDAR MONITOR LOCKS session USING session: Session IMPORTS Process, RefTab, SymTab EXPORTS BridgeExec ~ { OPEN BridgeExec; NetworkStream: TYPE ~ IO.STREAM; ROPE: TYPE ~ Rope.ROPE; <> Registration: TYPE ~ REF RegistrationObject; RegistrationObject: TYPE ~ RECORD [ name: ROPE, createProc: CreateProc, clientData: REF, destroyProc: DestroyProc ]; registrationTab: SymTab.Ref _ SymTab.Create[]; Register: PUBLIC PROC [name: ROPE, createProc: CreateProc, clientData: REF, destroyProc: DestroyProc] ~ { IF createProc = NIL THEN { [] _ SymTab.Delete[x~registrationTab, key~name] } ELSE { r: Registration _ NEW[RegistrationObject _ [name, createProc, clientData, destroyProc]]; [] _ SymTab.Store[x~registrationTab, key~name, val~r] }; }; GetRegistration: PROC [name: ROPE] RETURNS [registration: Registration] ~ { val: REF; [val~val] _ SymTab.Fetch[x~registrationTab, key~name]; registration _ NARROW[val]; }; <> Session: TYPE ~ REF SessionObject; SessionObject: PUBLIC TYPE ~ MONITORED RECORD [ name: ROPE, locks: NAT _ 0, unlocked: CONDITION, dead: BOOL _ FALSE, creationTab: RefTab.Ref ]; CreateSession: PUBLIC PROC [sessionName: ROPE] RETURNS [newSession: Session] ~ { newSession _ NEW[SessionObject _ [name~sessionName, creationTab~RefTab.Create[]]]; }; DestroySession: PUBLIC PROC [session: Session] ~ { TRUSTED { Process.Detach[ FORK DestroySessionWorker[session] ] }; }; DestroySessionWorker: PROC [session: Session] ~ { DestroyOne: RefTab.EachPairAction -- [key, val] RETURNS [quit] -- ~ { DestroyInstance[session, NARROW[key], NIL]; RETURN [FALSE] }; KillSessionWhenUnlocked[session]; [] _ RefTab.Pairs[x~session.creationTab, action~DestroyOne]; }; KillSessionWhenUnlocked: ENTRY PROC [session: Session] ~ { ENABLE UNWIND => NULL; WHILE session.locks > 0 DO WAIT session.unlocked ENDLOOP; session.dead _ TRUE; }; LockSession: ENTRY PROC [session: Session] RETURNS [ok: BOOL] ~ { ENABLE UNWIND => NULL; IF session.dead THEN RETURN [FALSE] ELSE { session.locks _ session.locks.SUCC; RETURN [TRUE] }; }; UnlockSession: ENTRY PROC [session: Session] ~ { ENABLE UNWIND => NULL; IF (session.locks _ session.locks.PRED) = 0 THEN BROADCAST session.unlocked; }; SessionNameFromSession: PUBLIC PROC [session: Session] RETURNS [sessionName: ROPE] ~ { RETURN [session.name] }; SessionIsDead: PUBLIC ENTRY PROC [session: Session] RETURNS [dead: BOOL] ~ { ENABLE UNWIND => NULL; RETURN [session.dead] }; <> Creation: TYPE ~ REF CreationObject; CreationObject: TYPE ~ RECORD [ registration: Registration, args: ROPE, instance: Instance ]; CreateInstance: PUBLIC PROC [cmdName: ROPE, s: NetworkStream, args: ROPE, session: Session] RETURNS [instance: Instance _ NIL] ~ { registration: Registration; creation: Creation; registration _ GetRegistration[cmdName]; IF registration = NIL THEN RETURN; IF NOT LockSession[session] THEN RETURN; instance _ registration.createProc[s, args, session, registration.clientData]; IF instance = NIL THEN { UnlockSession[session]; RETURN }; creation _ NEW[CreationObject _ [registration, args, instance]]; [] _ RefTab.Store[x~session.creationTab, key~instance, val~creation]; UnlockSession[session]; }; DestroyInstance: PUBLIC PROC [session: Session, instance: Instance, clientData: REF] ~ { creation: Creation _ DeleteCreationFromSession[session, instance]; IF creation # NIL THEN creation.registration.destroyProc[instance, clientData]; creation.instance _ NIL; -- help break cycles for garbage collector }; DeleteCreationFromSession: ENTRY PROC [session: Session, instance: Instance] RETURNS [creation: Creation] ~ { ENABLE UNWIND => NULL; val: REF; [val~val] _ RefTab.Fetch[x~session.creationTab, key~instance]; [] _ RefTab.Delete[x~session.creationTab, key~instance]; creation _ NARROW[val]; }; }...