BridgeExecImpl.mesa
Copyright Ó 1992 by Xerox Corporation. All rights reserved.
Demers, May 11, 1990 5:10 pm PDT
Christian Le Cocq September 30, 1987 4:52:13 pm PDT
Eduardo Pelegri-Llopart April 5, 1989 6:05:12 am PDT
DIRECTORY
BridgeExec,
Process,
RefTab,
Rope,
SymTab
;
BridgeExecImpl: CEDAR MONITOR
LOCKS session USING session: Session
IMPORTS Process, RefTab, SymTab
EXPORTS BridgeExec
~ {
CreateProc: TYPE ~ BridgeExec.CreateProc;
DestroyProc: TYPE ~ BridgeExec.DestroyProc;
Instance: TYPE ~ BridgeExec.Instance;
NetworkStreamPair: TYPE ~ BridgeExec.NetworkStreamPair;
ROPE: TYPE ~ Rope.ROPE;
Command Registration
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 Management
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]];
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] };
Instance Management
Creation: TYPE ~ REF CreationObject;
CreationObject: TYPE ~ RECORD [
registration: Registration,
args: ROPE,
nsp: NetworkStreamPair,
close: PROC[nsp: NetworkStreamPair],
instance: Instance
];
CreateInstance: PUBLIC PROC [cmdName: ROPE, nsp: NetworkStreamPair, args: ROPE, session: Session, close: PROC[nsp: NetworkStreamPair]] RETURNS [instance: Instance ¬ NIL] ~ {
registration: Registration;
creation: Creation;
registration ¬ GetRegistration[cmdName];
IF registration = NIL THEN RETURN;
IF registration.createProc = NIL THEN RETURN;
IF NOT LockSession[session] THEN RETURN;
instance ¬ registration.createProc[nsp, args, session, registration.clientData];
IF instance = NIL THEN { UnlockSession[session]; RETURN };
creation ¬ NEW[CreationObject ¬ [registration, args, nsp, close, instance]];
[] ¬ RefTab.Store[x~session.creationTab, key~instance, val~creation];
UnlockSession[session];
};
DestroyInstance: PUBLIC PROC [session: Session, instance: Instance, clientData: REF ¬ NIL] ~ {
creation: Creation ¬ DeleteCreationFromSession[session, instance];
IF creation # NIL THEN TRUSTED {
Process.Detach[ FORK DestroyInstanceInner[creation, instance, clientData] ];
};
};
DestroyInstanceInner: PROC [creation: Creation, instance: Instance, clientData: REF] ~ {
creation.registration.destroyProc[instance, clientData];
IF creation.close#NIL THEN creation.close[creation.nsp];
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];
};
}...