DIRECTORY CedarProcess, CD USING [Design], CDIO USING [WriteDesign], CDDrawQueue, CDVPrivate, CDViewer USING [DesignOf], CDSequencer, IO USING [PutFR, int], Process USING [Detach, MsecToTicks, Pause, SecondsToTicks], Rope USING [ROPE, IsEmpty], RuntimeError USING [UNCAUGHT], Terminal USING [GetKeys, Virtual, Current], TerminalIO USING [PutRope, PutRopes], ViewerClasses USING [ViewerClass, SaveProc], ViewerOps USING [FetchViewerClass, EnumerateViewers, EnumProc]; CDEmergencyHandling: CEDAR MONITOR IMPORTS CedarProcess, CDIO, CDDrawQueue, CDVPrivate, CDViewer, CDSequencer, IO, Process, Rope, RuntimeError, Terminal, TerminalIO, ViewerOps SHARES CDVPrivate = BEGIN SaveAll: PROC [] = { OneViewer: ViewerOps.EnumProc = { design: CD.Design = CDViewer.DesignOf[v].design; -- is not monitored IF design#NIL THEN Save[v, TRUE] }; ViewerOps.EnumerateViewers[OneViewer] }; StopDrawing: PROC[] = { ENABLE RuntimeError.UNCAUGHT => GOTO exit; FOR l: LIST OF CDVPrivate.VRef _ CDVPrivate.allVRefs, l.rest WHILE l#NIL DO IF l.first.ct#NIL THEN CDDrawQueue.Flush[l.first.ct] ENDLOOP; EXITS exit => NULL; }; StopDrawingCommand: PROC [comm: CDSequencer.Command] = { TerminalIO.PutRope["Stop drawing (better use )\n"]; StopDrawing[]; }; EmergencySaveProcess: PROC = { virtual: Terminal.Virtual _ Terminal.Current[]; CedarProcess.SetPriority[CedarProcess.Priority[foreground]]; DO -- for nearly ever Process.Pause[Process.SecondsToTicks[1]]; IF Terminal.GetKeys[virtual][ESC]=down AND Terminal.GetKeys[virtual][LF]=down THEN StopDrawing[]; IF Terminal.GetKeys[virtual][Spare3]=down AND Terminal.GetKeys[virtual][RightShift]=down AND Terminal.GetKeys[virtual][LeftShift]=down THEN { SaveAll[]; TerminalIO.PutRope["\nsaved ChipNDale viewers; works only once\n"]; RETURN } ENDLOOP; }; Save: ViewerClasses.SaveProc --PROC [self: Viewer, force: BOOL _ FALSE]-- = { IF force AND ~self.saveInProgress THEN { design: CD.Design = CDViewer.DesignOf[self].design; -- is not monitored IF design#NIL THEN { TRUSTED {Process.Detach[FORK SaveDesign[design]]}; } } }; SaveDesign: PROC[design: CD.Design] = { done: BOOL _ FALSE; fileName: Rope.ROPE; ReallySaveDesign: ENTRY PROC[design: CD.Design] = { ENABLE { UNWIND => NULL; RuntimeError.UNCAUGHT => GOTO next; }; FOR list: LIST OF CD.Design _ savedDesigns, list.rest WHILE list#NIL DO IF list.first=design THEN RETURN; ENDLOOP; fileName _ IO.PutFR["///temp/ChipNDale/emergencysave%01g.dale", IO.int[saveKey^]]; saveKey^ _ saveKey^+1; done _ CDIO.WriteDesign[design: design, to: fileName, emergency: TRUE]; IF done THEN savedDesigns _ CONS[design, savedDesigns]; EXITS next => NULL }; Process.Pause[Process.MsecToTicks[100]]; -- give the detached Flush process a chance ReallySaveDesign[design]; IF done THEN { TerminalIO.PutRopes["design ", (IF Rope.IsEmpty[design.name] THEN "no name" ELSE design.name)]; TerminalIO.PutRopes[" saved on file """, fileName, """\nWARNING: This write was made out of synchronisation; (what means: if any other process was fooling with the design, both could be broken, the design, and the file). Roll back, Copy the file and CHECK it.\n"]; } }; savedDesigns: LIST OF CD.Design _ NIL; saveKey: REF INT = NEW[INT_0]; -- ref used as key; referent used as counter class: ViewerClasses.ViewerClass = ViewerOps.FetchViewerClass[$ChipNDale]; IF class#NIL AND class.save=NIL THEN class.save _ Save; TRUSTED {Process.Detach[FORK EmergencySaveProcess[]]}; CDSequencer.ImplementCommand[$StopDrawing, StopDrawingCommand,, dontQueue]; END. πCDEmergencyHandling.mesa Copyright c 1984 by Xerox Corporation. All rights reserved. Created by Christian Jacobi, July 13, 1984 9:11:20 am PDT Last edited by: Christian Jacobi, September 18, 1986 2:02:01 pm PDT --I checked the implementation; --ViewerOps.EnumerateViewers then was really not monitored -- -- -- -- -- -- -- -- -- -- -- -- now real stuff --otherwise don't consider saving --vanilla try to avoid concurrency with the write, which is unmonitored; --forked, so save may not hang in MBQueue monitor locking on the design TRUSTED {Process.Detach[FORK MBQueue.Flush[design.queue]]}; --forked, so save of other designs may not hang --using our own monitor prevents it at least from wedging together with other's; --we must use some monitor because emergencywrite tries to kill any interferences, --which could be other emergencywrite's --we use the list business to prevent multiple save instead of CDValue, --to never call any monitored procedure which could cause additional wedges Κ6˜codešœ™Kšœ Οmœ1™˜ŒKšžœ˜—Kšž˜K˜šŸœžœ˜šΠbn œ˜!Kšœžœ(Οc˜EKšžœžœžœ žœ˜ Kšœ˜—Kšœ ™ Kšœ:™:Kšœ%˜%Kšœ˜—K˜š  œžœ˜Kšžœžœžœ˜*š žœžœžœ/žœžœž˜KKšžœ žœžœ˜4Kšžœ˜—Kšžœ žœ˜Kšœ˜—K˜šŸœžœ ˜8K˜=Kšœ˜Kšœ˜—K˜šŸœžœ˜Kšœ/˜/Kšœ<˜<šžœ‘˜K˜)šžœžœ˜'Kšžœžœ˜&Kšžœ˜—šžœ'˜)Kšžœ+˜.Kšžœ*˜-šžœ˜Kšœ ˜ KšœC˜CKšž˜Kšœ˜——Kšžœ˜—Kšœ˜K˜—K˜KšΟb!™!K™K™š’œ‘,œ˜Mšžœžœžœ˜(Kšœ!™!Kšœžœ,‘˜Išžœžœžœ˜K˜KšœH™HKšœG™GKšžœžœ!™=K˜Kšœ/™/Kšžœžœ˜2K˜Kšœ˜—Kšœ˜—Kšœž˜—K˜šŸ œžœ žœ ˜'Kšœžœžœ˜Kšœžœ˜K˜KšœP™PKšœR™RKšœ(™(šŸœžœžœ žœ ˜3šžœ˜Kšžœžœ˜Kšœ žœžœ˜#Kšœ˜—KšœH™HKšœK™Kš žœžœžœžœ"žœžœž˜GKšžœžœžœ˜!Kšžœ˜—Kšœ žœ3žœ˜RKšœ˜Kšœžœ6žœ˜GKšžœžœžœ˜7Kšžœ ž˜Kšœ˜—K˜Kšœ)‘+˜TKšœ˜šžœžœ˜Kšœ žœžœ žœ˜`Kšœˆ˜ˆK˜—Kšœ˜—K˜K˜Kš œžœžœžœ žœ˜&Kš œ žœžœžœžœ‘-˜LKšœJ˜JKš žœžœžœ žœžœ˜7Kšžœžœ˜6KšœK˜KKšžœ˜K˜—…— Ύδ