<> <> <> <<>> DIRECTORY Basics USING [BITXOR, HighHalf, LowHalf], FSLock USING [ActiveFile, ActiveFileObject], FSBackdoor USING [Version], Rope USING [Concat, Equal, Match, ROPE], RopeHash USING [FromRope]; FSLockTableImpl: CEDAR MONITOR IMPORTS Basics, Rope, RopeHash EXPORTS FSLock = { ROPE: TYPE = Rope.ROPE; <> <<>> LookupLock: PUBLIC ENTRY PROC [prefix, nameBody: ROPE, version: FSBackdoor.Version] RETURNS [a: FSLock.ActiveFile] = { ENABLE UNWIND => NULL; hash: CARDINAL; IF NOT Rope.Match["[*", nameBody] THEN nameBody _ Rope.Concat[prefix, nameBody]; hash _ RopeHash.FromRope[rope: nameBody, case: FALSE, seed: version] MOD buckets; stats.lookups _ stats.lookups + 1; FOR a _ lockTbl[hash], a.next UNTIL a = NIL DO IF version = a.version AND Rope.Equal[nameBody, a.nameBody, FALSE] THEN RETURN; ENDLOOP; stats.newActiveFiles _ stats.newActiveFiles + 1; a _ NEW [FSLock.ActiveFileObject]; a.nameBody _ nameBody; a.version _ version; a.h _ NIL; a.fileLock _ none; a.recordLock _ FALSE; a.fileLockCount _ 0; a.attachedTo _ NIL; a.next _ lockTbl[hash]; lockTbl[hash] _ a; }; RemoveLock: PUBLIC ENTRY PROC [a: FSLock.ActiveFile] = { ENABLE UNWIND => NULL; hash: CARDINAL = RopeHash.FromRope[rope: a.nameBody, case: FALSE, seed: a.version] MOD buckets; aPrev: FSLock.ActiveFile _ lockTbl[hash]; stats.removals _ stats.removals + 1; IF aPrev = a THEN lockTbl[hash] _ a.next ELSE DO IF aPrev.next = a THEN {aPrev.next _ a.next; EXIT}; aPrev _ aPrev.next; ENDLOOP; a.nameBody _ NIL; }; RecordREF: PUBLIC ENTRY PROC [r: REF] = { p: REF PRTEntry = NEW [PRTEntry]; hash: CARDINAL = RefHash[r]; p.ref _ r; p.chain _ prt[hash]; prt[hash] _ p; stats.prtRecorded _ stats.prtRecorded + 1; }; RemoveREF: PUBLIC ENTRY PROC [r: REF] = { hash: CARDINAL = RefHash[r]; p, q: REF PRTEntry; q _ prt[hash]; IF q.ref = r THEN prt[hash] _ q.chain ELSE DO p _ q; q _ q.chain; IF q.ref = r THEN {p.chain _ q.chain; EXIT}; ENDLOOP; q.ref _ NIL; stats.prtRemoved _ stats.prtRemoved + 1; }; <> <<>> StatsRecord: TYPE = RECORD [ lookups: INT _ 0, newActiveFiles: INT _ 0, removals: INT _ 0, prtRecorded: INT _ 0, prtRemoved: INT _ 0 ]; stats: REF StatsRecord = NEW[StatsRecord]; <> <<>> buckets: CARDINAL = 109; LockTable: TYPE = ARRAY [0..buckets) OF FSLock.ActiveFile; lockTbl: REF LockTable _ NEW [LockTable _ ALL[NIL]]; <> prtBuckets: CARDINAL = 109; PackageReferenceTable: TYPE = ARRAY [0..prtBuckets) OF REF PRTEntry; PRTEntry: TYPE = RECORD [chain: REF PRTEntry, ref: REF]; prt: REF PackageReferenceTable _ NEW [PackageReferenceTable _ ALL[NIL]]; RefHash: PROC [r: REF] RETURNS [CARDINAL] = INLINE { RETURN [Basics.BITXOR[Basics.LowHalf[LOOPHOLE[r, LONG CARDINAL]], Basics.HighHalf[LOOPHOLE[r, LONG CARDINAL]]] MOD prtBuckets]; }; }.