DIRECTORY TEditLocks, TEditLocksPrivate, Process USING [GetCurrent], MonitoredQueue USING [AddToSet], Rope USING [ROPE], TextNode USING [Ref], TEditDocument USING [GetViewerForRoot, SpinAndLock, TEditDocumentData, Unlock], TEditRefresh USING [dirtyDocs], ViewerClasses USING [Viewer]; TEditLocksImpl: CEDAR MONITOR LOCKS lock USING lock: LockRef IMPORTS TEditLocks, TEditLocksPrivate, Process, MonitoredQueue, TEditDocument, TEditRefresh EXPORTS TEditLocks = BEGIN OPEN TEditLocks, TEditDocument; LockBoth: PUBLIC PROC [doc1, doc2: TextNode.Ref, who: Rope.ROPE, access1, access2: Access _ write] RETURNS [lock1, lock2: LockRef] = { IF (doc1=doc2 AND access1=write) OR (doc1 # doc2 AND LockOrder[doc1, doc2]) THEN { lock1 _ Lock[doc1, who, access1]; lock2 _ Lock[doc2, who, access2] } ELSE { lock2 _ Lock[doc2, who, access2]; lock1 _ Lock[doc1, who, access1] }}; Lock: PUBLIC PROC [doc: TextNode.Ref, who: Rope.ROPE, access: Access _ write] RETURNS [lock: LockRef] = { IF doc=NIL THEN ERROR; IF (lock _ TEditLocksPrivate.GetLock[doc])=NIL THEN RETURN; LockIt[lock, who, access, doc]; }; LockIt: ENTRY PROC [lock: LockRef, who: Rope.ROPE, access: Access, doc: TextNode.Ref] = { ENABLE UNWIND => NULL; myProcess: PROCESS; TRUSTED {myProcess _ LOOPHOLE[Process.GetCurrent[]]}; IF access=read THEN { IF lock.process # myProcess THEN WHILE lock.process # NIL DO -- wait for write lock to clear WAIT lock.unlocked; ENDLOOP } ELSE { -- want write access IF lock.process # myProcess THEN { -- I don't have a write lock on it already IF lock.count > 0 THEN { -- doc is locked lock.waitingForWrite _ lock.waitingForWrite+1; WHILE lock.count > 0 DO -- wait for all locks to clear WAIT lock.unlocked; ENDLOOP; lock.waitingForWrite _ lock.waitingForWrite-1 }; lock.process _ myProcess }}; IF lock.count=0 THEN lock.whoFirst _ who ELSE lock.whoLast _ who; lock.count _ lock.count+1; lock.maxCount _ MAX[lock.maxCount, lock.count] }; Unlock: PUBLIC PROC [doc: TextNode.Ref] = { lock: LockRef; IF doc=NIL THEN ERROR; IF (lock _ TEditLocksPrivate.GetLock[doc])=NIL THEN RETURN; UnlockIt[lock, doc]; }; UnlockIt: ENTRY PROC [lock: LockRef, doc: TextNode.Ref] = { ENABLE UNWIND => NULL; IF lock=NIL THEN RETURN; IF lock.count <= 0 THEN ERROR; TRUSTED {IF lock.process # NIL AND lock.process # Process.GetCurrent[] THEN ERROR}; IF (lock.count _ lock.count-1) > 0 THEN RETURN; -- still locked IF lock.process # NIL THEN { -- had write lock viewer: ViewerClasses.Viewer; IF (viewer _ TEditDocument.GetViewerForRoot[doc]) # NIL THEN { MarkDirty: PROC [v: ViewerClasses.Viewer] = { tdd: TEditDocument.TEditDocumentData _ NARROW[v.data]; IF tdd#NIL THEN tdd.dirty _ TRUE }; MarkDirty[viewer]; IF viewer.link # NIL THEN FOR v: ViewerClasses.Viewer _ viewer.link, v.link UNTIL v=viewer DO MarkDirty[v]; ENDLOOP; MonitoredQueue.AddToSet[doc, TEditRefresh.dirtyDocs] }; lock.process _ NIL }; lock.whoFirst _ lock.whoLast _ NIL; lock.maxCount _ 0; BROADCAST lock.unlocked; }; LockDocAndTdd: PUBLIC PROC [tdd: TEditDocument.TEditDocumentData, who: Rope.ROPE, access: Access _ write, interrupt, defer: BOOL _ FALSE] RETURNS [lock: LockRef] = { IF ~TEditDocument.SpinAndLock[tdd, "LockDocAndTdd1", interrupt, defer] THEN RETURN [NIL]; DO doc: TextNode.Ref _ tdd.text; TEditDocument.Unlock[tdd]; -- must unlock tdd before try to lock the document. IF doc=NIL THEN RETURN [NIL]; lock _ Lock[doc, who, access]; IF ~TEditDocument.SpinAndLock[tdd, "LockDocAndTdd2", interrupt, defer] THEN { UnlockIt[lock, doc]; RETURN [NIL] }; IF tdd.text = doc THEN RETURN; -- all went well UnlockIt[lock, doc]; -- document changed during the time we had tdd unlocked ENDLOOP }; UnlockDocAndTdd: PUBLIC PROC [tdd: TEditDocument.TEditDocumentData] = { IF tdd.text#NIL THEN Unlock[tdd.text]; TEditDocument.Unlock[tdd] }; END... ΰTEditLocksImpl.mesa Edited by Paxton on November 5, 1982 10:25 am Last Edited by: Maxwell, January 6, 1983 11:43 am Like two calls on Lock, but orders the calls according to LockOrder. must lock before read tdd.text Κί˜JšœA™AJšΟk1™1š ˜ Jšœ ˜ Jšœ˜Jšœœ˜Jšœœ ˜ Jšœœœ˜Jšœ œ˜Jšœœ<˜OJšœ œ ˜Jšœœ ˜J˜—šœ ˜Jšœœ˜—J˜JšœT˜[Jšœœœ˜:J˜šΟnœœœ&œ˜@Jšœ"œ˜EJšœD™Dš œ œœœœ˜RJšœD˜D—JšœI˜MJ™—šžœ œœœ˜iJšœœœœ˜Jšœ)œœœ˜;J˜˜J˜——unitšžœœœœ(˜YJšœœœ˜Jšœ œ˜Jšœœ˜5codešœ œ˜šœ˜ šœœœΟc˜;Lšœœ˜———šœŸ˜šœœŸ*˜MšœœŸ˜)L˜.šœœŸ˜6Lšœœ˜—L˜0—Lšœ˜——Lšœœœ˜AL˜Lšœœ˜1—J˜šžœœœ˜+Jšœ˜Jšœœœœ˜Jšœ)œœœ˜;J˜J˜—J˜šžœœœ'˜;Jšœœœ˜Jšœœœœ˜Jšœœœ˜Jš œœœœ%œœ˜SJšœ!œœŸ˜?šœœœŸ˜.Lšœ˜šœ2œœ˜>šž œœ˜-Lšœ'œ ˜6Lšœœœ œ˜#—Lšœ˜šœœ˜šœ/œ ˜CJšœ œ˜——Jšœ7˜7—Jšœœ˜—Jšœœ˜#J˜Jš œ˜J˜—J˜šž œœœ'˜AJšœ œ,œœ˜GJšœ˜šœEœœœ˜YJšœ™—š˜J˜JšœŸ3˜NJš œœœœœ˜Jšœ˜šœEŸœ˜MJšœœœ˜$—JšœœœŸ˜/JšœŸ7˜LJšœ˜ ——J˜šžœ œ+˜GJšœ œœ˜&Jšœ˜—J˜Jšœ˜—…—Ζ