DIRECTORY FS USING [Lock], FSBackdoor USING [Version], FSLock USING [ActiveFile, LookupLock, RemoveLock], Rope USING [ROPE]; FSLockImpl: CEDAR MONITOR LOCKS a USING a: FSLock.ActiveFile IMPORTS FSLock EXPORTS FSLock = { ActiveFile: TYPE = FSLock.ActiveFile; ROPE: TYPE = Rope.ROPE; Version: TYPE = FSBackdoor.Version; LockRecord: PUBLIC PROC [volumePrefix, nameBody: ROPE, version: Version] RETURNS [a: ActiveFile, ok: BOOL] = { InnerLockRecord: ENTRY PROC [a: ActiveFile] RETURNS [{gotIt, wait, dead}] = { IF a.nameBody = NIL THEN RETURN [dead]; IF a.recordLock THEN RETURN [wait]; a.recordLock _ TRUE; RETURN [gotIt]; }; DO a _ FSLock.LookupLock[volumePrefix, nameBody, version]; SELECT InnerLockRecord[a] FROM gotIt => ok _ TRUE; wait => ok _ FALSE; dead => LOOP; ENDCASE => ERROR; EXIT; ENDLOOP; }; checkAgain: CONDITION; LockAttachedToRecord: PUBLIC PROC [a: ActiveFile] = { InnerLockAttachedToRecord: PUBLIC ENTRY PROC [a: ActiveFile] = { ENABLE UNWIND => NULL; WHILE a.recordLock DO WAIT checkAgain ENDLOOP; IF a.nameBody = NIL THEN ERROR; a.recordLock _ TRUE; }; IF NOT a.recordLock THEN ERROR; InnerLockAttachedToRecord[a.attachedTo]; }; WaitForRecord: PUBLIC ENTRY PROC [a: ActiveFile] = { ENABLE UNWIND => NULL; WHILE a.nameBody # NIL AND a.recordLock DO WAIT checkAgain ENDLOOP; }; ReleaseRecord: PUBLIC PROC [a: ActiveFile] = { InnerReleaseRecord: ENTRY PROC [a: ActiveFile] = { ENABLE UNWIND => NULL; IF a.recordLock THEN { a.recordLock _ FALSE; IF a.fileLockCount = 0 THEN FSLock.RemoveLock[a]; BROADCAST checkAgain; }; }; IF a = NIL THEN RETURN; -- release of NIL is a nop! InnerReleaseRecord[a]; }; LockFile: PUBLIC ENTRY PROC [a: ActiveFile, lock: FS.Lock] RETURNS [ok: BOOL] = { ENABLE UNWIND => NULL; IF NOT a.recordLock THEN ERROR; IF a.fileLockCount = 0 THEN a.fileLock _ (IF lock = write THEN write ELSE read) ELSE { IF lock = write OR (lock = read AND a.fileLock = write) THEN RETURN [FALSE] }; a.fileLockCount _ a.fileLockCount + 1; RETURN [TRUE]; }; GetAttachment: PUBLIC ENTRY PROC [a: ActiveFile] RETURNS [ActiveFile] = { ENABLE UNWIND => NULL; WHILE a.recordLock DO WAIT checkAgain ENDLOOP; IF a.fileLockCount = 0 THEN ERROR; RETURN [a.attachedTo]; }; ReportClose: PUBLIC PROC [a: ActiveFile] = { ReleaseFile: ENTRY PROC [a: ActiveFile] RETURNS [attachedTo: ActiveFile] = { ENABLE UNWIND => NULL; WHILE a.recordLock DO WAIT checkAgain ENDLOOP; IF a.fileLockCount = 0 THEN ERROR; attachedTo _ a.attachedTo; a.fileLockCount _ a.fileLockCount - 1; IF a.fileLockCount = 0 THEN { a.fileLock _ none; IF NOT a.recordLock THEN FSLock.RemoveLock[a]; }; }; att: ActiveFile _ ReleaseFile[a]; IF att # NIL THEN att _ ReleaseFile[att]; IF att # NIL THEN ERROR; }; }. θFSLockImpl.mesa Copyright c 1984 by Xerox Corporation. All rights reserved. Russ Atkinson, November 7, 1984 11:27:51 am PST Schroeder, November 15, 1983 1:29 pm Procedures exported to FSLock may be no record lock to release Κ9– "cedar" style˜šœ™Jšœ Οmœ1™