-- CedarSnapshotRegistry.mesa -- last edited by Levin: September 7, 1982 1:00 pm DIRECTORY CedarSnapshot USING [CheckpointProc, RollbackProc], CedarSnapshotPrivate USING [], Heap USING [systemZone], Inline USING [LongCOPY]; CedarSnapshotRegistry: MONITOR IMPORTS Heap, Inline EXPORTS CedarSnapshot, CedarSnapshotPrivate = BEGIN Registry: TYPE = LONG POINTER TO Procs; Procs: TYPE = RECORD [ nProcs: CARDINAL _ 0, procs: SEQUENCE nSlots: CARDINAL OF RegisteredProc _ NULL]; RegisteredProc: TYPE = PROC; initialProcs: CARDINAL = 10; incrementProcs: CARDINAL = 5; checkpointRegistry, rollbackRegistry: Registry _ NIL; ProcAlreadyRegistered: ERROR = CODE; ProcNotRegistered: ERROR = CODE; -- Procedures exported to CedarSnapshot Register: PUBLIC ENTRY PROC [ c: CedarSnapshot.CheckpointProc _ NIL, r: CedarSnapshot.RollbackProc _ NIL] = {AddProc[@checkpointRegistry, LOOPHOLE[c]]; AddProc[@rollbackRegistry, LOOPHOLE[r]]}; Deregister: PUBLIC ENTRY PROC [ c: CedarSnapshot.CheckpointProc _ NIL, r: CedarSnapshot.RollbackProc _ NIL] = {RemoveProc[@checkpointRegistry, LOOPHOLE[c]]; RemoveProc[@rollbackRegistry, LOOPHOLE[r]]}; -- Procedures exported to CedarSnapshotPrivate -- The enumerators call the caller-supplied procedure outside the monitor, permitting -- Register/Deregister to be called from within the enumeration. EnumerateCheckpointProcs: PUBLIC PROC [proc: PROC [CedarSnapshot.CheckpointProc]] = { i: CARDINAL _ LAST[CARDINAL]; p: CedarSnapshot.CheckpointProc; GetNext: ENTRY PROC RETURNS [p: CedarSnapshot.CheckpointProc] = INLINE { p _ NIL; i _ MIN[i, checkpointRegistry.nProcs]; IF i > 0 THEN { i _ i - 1; p _ LOOPHOLE[checkpointRegistry.procs[i]]; }; }; IF checkpointRegistry = NIL THEN RETURN; UNTIL (p _ GetNext[]) = NIL DO proc[p]; ENDLOOP; }; EnumerateRollbackProcs: PUBLIC PROC [proc: PROC [CedarSnapshot.RollbackProc]] = { i: CARDINAL _ 0; p: CedarSnapshot.RollbackProc; GetNext: ENTRY PROC RETURNS [p: CedarSnapshot.RollbackProc] = INLINE { p _ NIL; IF i < rollbackRegistry.nProcs THEN { p _ LOOPHOLE[rollbackRegistry.procs[i]]; i _ i + 1; }; }; IF rollbackRegistry = NIL THEN RETURN; UNTIL (p _ GetNext[]) = NIL DO proc[p]; ENDLOOP; }; -- Private Procedures AddProc: INTERNAL PROC [registry: LONG POINTER TO Registry, proc: RegisteredProc] = { IF proc = NIL THEN RETURN; IF registry^ = NIL THEN registry^ _ Heap.systemZone.NEW[Procs[initialProcs] _ []]; FOR i: CARDINAL IN [0..registry^.nProcs) DO IF registry^.procs[i] = proc THEN ERROR ProcAlreadyRegistered; ENDLOOP; IF registry^.nProcs = registry^.nSlots THEN { newRegistry: Registry _ Heap.systemZone.NEW[Procs[registry^.nSlots+incrementProcs] _ [nProcs: registry^.nProcs]]; Inline.LongCOPY[from: @registry^.procs[0], to: @newRegistry.procs[0], nwords: registry^.nSlots*SIZE[RegisteredProc]]; Heap.systemZone.FREE[registry]; registry^ _ newRegistry; }; registry^.procs[registry^.nProcs] _ proc; registry^.nProcs _ registry^.nProcs + 1; }; RemoveProc: INTERNAL PROC [registry: LONG POINTER TO Registry, proc: RegisteredProc] = { state: {looking, compressing} _ looking; FOR i: CARDINAL IN [0..registry^.nProcs) DO SELECT state FROM looking => IF registry^.procs[i] = proc THEN state _ compressing; compressing => registry^.procs[i - 1] _ registry^.procs[i]; ENDCASE; ENDLOOP; IF state = looking THEN ERROR ProcNotRegistered; registry^.nProcs _ registry^.nProcs - 1; }; END.