DIRECTORY IFSFile USING [AccessFailure, CantOpen, Error], IFSFilePrivate USING [FileHandle, FileObject, FSInstance], Rope USING [Equal, ROPE]; IFSFileImplE: MONITOR LOCKS fs.LOCK USING fs: IFSFilePrivate.FSInstance IMPORTS IFSFile, Rope EXPORTS IFSFilePrivate = { OPEN IFSFilePrivate; ROPE: TYPE = Rope.ROPE; FileListSmashed: ERROR = CODE; FileNotInList: ERROR = CODE; IllegalDestroy: ERROR = CODE; InvalidFile: ERROR = CODE; InsertFile: PUBLIC PROC [fs: FSInstance, name: ROPE, openProc: PROC [FileHandle] RETURNS [IFSFile.AccessFailure]] RETURNS [file: FileHandle] = { NewlyOpened: ENTRY PROC [fs: FSInstance] RETURNS [BOOL] = { file _ fs.fileList; UNTIL file = NIL DO IF Rope.Equal[file.name, name, FALSE] THEN { SELECT file.seal FROM openSeal => {file.openCount _ file.openCount + 1; RETURN[FALSE]}; underwaySeal => {WAIT fs.changeInOpenState; file _ fs.fileList}; ENDCASE => GO TO bogusList } ELSE -- ensure pointer validity SELECT file.seal FROM openSeal, underwaySeal => file _ file.link; ENDCASE => GO TO bogusList; REPEAT bogusList => ERROR FileListSmashed; ENDLOOP; file _ NEW[FileObject _ FileObject[link: fs.fileList, name: name, fs: fs]]; fs.fileList _ file; RETURN[TRUE] }; AnnounceOutcome: ENTRY PROC [fs: FSInstance, outcome: IFSFile.AccessFailure] = { IF outcome = ok THEN file.seal _ openSeal ELSE RemoveFile[fs, file]; BROADCAST fs.changeInOpenState; SELECT outcome FROM ok => RETURN; io => RETURN WITH ERROR IFSFile.Error[io]; ENDCASE => RETURN WITH ERROR IFSFile.CantOpen[outcome]; }; IF NewlyOpened[fs] THEN AnnounceOutcome[fs, openProc[file]]; }; ReleaseFile: PUBLIC PROC [file: FileHandle, closeProc: PROC [FileHandle]] = { IF LastReference[file.fs, file] THEN {closeProc[file]; FlushFile[file]}; }; PurgeFile: PUBLIC PROC [file: FileHandle, destroyProc: PROC [FileHandle]] = { IF LastReference[file.fs, file] THEN {destroyProc[file]; FlushFile[file]} ELSE ERROR IllegalDestroy; }; LastReference: ENTRY PROC [fs: FSInstance, file: FileHandle] RETURNS [last: BOOL] = { IF file.seal ~= openSeal OR file.openCount = 0 THEN ERROR InvalidFile; IF (last _ file.openCount = 1) THEN file.seal _ underwaySeal ELSE file.openCount _ file.openCount - 1; RETURN[last] }; FlushFile: PROC [file: FileHandle] = { DoRemoveFile: ENTRY PROC [fs: FSInstance] = {RemoveFile[fs, file]; BROADCAST fs.changeInOpenState}; DoRemoveFile[file.fs]; }; RemoveFile: INTERNAL PROC [fs: FSInstance, file: FileHandle] = { IF file = fs.fileList THEN fs.fileList _ file.link ELSE { IF fs.fileList = NIL THEN GO TO Trouble; FOR prev: FileHandle _ fs.fileList, prev.link UNTIL prev.link = NIL DO IF prev.link = file THEN {prev.link _ file.link; EXIT}; REPEAT FINISHED => GO TO Trouble; ENDLOOP; EXITS Trouble => ERROR FileNotInList; }; file.seal _ closedSeal; -- try to catch dangling references }; }.  IFSFileImplE.mesa Copyright c 1985 by Xerox Corporation. All rights reserved. Levin - 2-Jul-81 10:14:42 Russ Atkinson, March 7, 1985 2:21:40 pm PST Miscellaneous Procedures and Signals Exported to IFSFilePrivate checks to see if the file identified by 'name' has already been entered in the file list. If not, it enters it and indicates that the open operation is underway. If so, it waits for any previous open attempt to be resolved, then reports the outcome. Internal Procedures removes the file from the list. Κœ˜codešœ™Kšœ Οmœ1™