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. DCedar Nucleus (Files): global table of open files (to cause sharing of handles) FileTableImpl.mesa Andrew Birrell June 27, 1983 4:42 pm Last Edited by: Levin, May 20, 1983 5:19 pm Last Edited by: Schroeder, June 10, 1983 5:20 pm The LOOPHOLE below is "respectable", since all we want is a decent hash function (?). Ê=˜JšœP™PJšœ™Jšœ%™%J™+J™0šÏk ˜ Jšœœ˜Jšœ œ ˜2Jšœ œ˜Jšœ œY˜j—J˜šœœ˜Jšœ˜!Jšœ ˜Jšœ˜ —J˜Jš˜J˜Jšœ œ ˜J˜Jšœœœ œ˜5J˜Jš œœ œ œœ˜)J˜šÏnœœœ ˜0JšœU™UJšœœœ ˜>—J˜š žœœœœ'œ˜eJš˜Jšœœœ˜J˜Jšœœ˜ J˜š˜Jšœ˜ šœ˜ Jšœ˜J˜J˜Jšœœœœ˜9J˜%Jš˜Jšœ˜—Jš œœœœœ˜PJ˜—Jšœ˜Jšœ˜—J˜Jšœœœ˜J˜šžœœœœ˜5Jš˜Jšœœœ˜Jšœ˜Jšœœ˜ Jšœ%˜%š˜Jšœ˜ šœ˜ Jšœœœœ˜7Jšœ$˜$Jš˜Jšœ˜—Jšœœœœ˜QJ˜—Jšœ˜Jšœ˜—J˜šžœœœ˜1Jš˜Jšœœœ˜J˜Jšœœ˜ Jšœ%˜%š˜Jšœœœœ˜Jšœ ˜ šœ˜ Jšœœœœ˜CJš˜Jšœ˜—J˜—Jšœ˜Jšœ˜—J˜š žœœœœœ˜@Jšœœœœ˜0—J˜šžœœœœ˜