<> <> <> <> <> DIRECTORY File USING[ FileID, Volume ], FileInternal USING[ FreeHeaderVM, Handle, Object], PrincOps USING[ LongNumber ], SafeStorage USING[ ClearFinalizedFlag, EstablishFinalization, FinalizationQueue, FQEmpty, FQNext, NewFQ ]; FileTableImpl: CEDAR MONITOR IMPORTS FileInternal, SafeStorage EXPORTS FileInternal SHARES File = BEGIN HashValue: TYPE = [0..256); Table: TYPE = ARRAY HashValue OF FileInternal.Handle; table: REF Table = NEW[Table _ ALL[NIL]]; Hash: PROC[id: File.FileID] RETURNS[HashValue] = <> { l: PrincOps.LongNumber = [li[LOOPHOLE[id]]]; RETURN[l.ll] }; Lookup: PUBLIC ENTRY PROC[volume: File.Volume, id: File.FileID] RETURNS [file: FileInternal.Handle] = BEGIN ENABLE UNWIND => NULL; h: HashValue = Hash[id]; prev: FileInternal.Handle _ NIL; file _ table[h]; DO IF file = NIL THEN BEGIN file _ InternalCreate[]; file.volume _ volume; file.fp.id _ id; IF prev = NIL THEN table[h] _ file ELSE prev.rest _ file; SafeStorage.ClearFinalizedFlag[file]; EXIT END; IF file.fp.id = id AND file.volume = volume THEN { file.reissued _ TRUE; EXIT }; prev _ file; file _ file.rest; ENDLOOP; END; ConfusedHash: ERROR = CODE; Insert: PUBLIC ENTRY PROC[new: FileInternal.Handle] = BEGIN ENABLE UNWIND => NULL; h: HashValue = Hash[new.fp.id]; prev: FileInternal.Handle _ NIL; file: FileInternal.Handle _ table[h]; DO IF file = NIL THEN BEGIN IF prev = NIL THEN table[h] _ new ELSE prev.rest _ new; SafeStorage.ClearFinalizedFlag[new]; EXIT END; IF file.fp.id = new.fp.id AND file.volume = new.volume THEN ERROR ConfusedHash[]; prev _ file; file _ file.rest; ENDLOOP; END; Remove: INTERNAL PROC[old: FileInternal.Handle] = BEGIN ENABLE UNWIND => NULL; h: HashValue = Hash[old.fp.id]; prev: FileInternal.Handle _ NIL; file: FileInternal.Handle _ table[h]; DO IF file = NIL THEN EXIT; IF file = old THEN BEGIN IF prev = NIL THEN table[h] _ file.rest ELSE prev.rest _ file.rest; EXIT END; prev _ file; file _ file.rest; ENDLOOP; END; AllocForCreate: PUBLIC ENTRY PROC RETURNS[FileInternal.Handle] = { RETURN[ InternalCreate[ ! UNWIND => NULL] ] }; InternalCreate: INTERNAL PROC RETURNS[FileInternal.Handle] = BEGIN UNTIL SafeStorage.FQEmpty[MyQueue] DO file: FileInternal.Handle = NARROW[SafeStorage.FQNext[MyQueue]]; IF file.reissued THEN { file.reissued _ FALSE; SafeStorage.ClearFinalizedFlag[file] } ELSE BEGIN Remove[file]; FileInternal.FreeHeaderVM[file]; END; ENDLOOP; RETURN[NEW[FileInternal.Object _ []]] END; DuplicateHashTableEntry: ERROR = CODE; MyQueue: SafeStorage.FinalizationQueue = SafeStorage.NewFQ[]; SafeStorage.EstablishFinalization[type: CODE[FileInternal.Object], npr: 1, fq: MyQueue]; END.