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];
};
}...