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