DIRECTORY BasicTime, Commander, Imager, ImagerBackdoor, IO, Loader, MessageWindow, PrincOps, PrincOpsUtils, Process, ProcessWatch, Rope, TIPUser, ViewerClasses, ViewerOps; ProcessWatchViewer: CEDAR MONITOR IMPORTS BasicTime, Commander, Imager, ImagerBackdoor, IO, Loader, MessageWindow, PrincOpsUtils, Process, ProcessWatch, TIPUser, ViewerOps = { ROPE: TYPE = Rope.ROPE; PsbIndex: TYPE = PrincOps.PsbIndex; UsefulPsbIndex: TYPE = ProcessWatch.UsefulPsbIndex; Viewer: TYPE = ViewerClasses.Viewer; ReadyVector: TYPE = ProcessWatch.ReadyVector; ProcessWatcher: TYPE = REF ProcessWatcherPrivate; ProcessWatcherPrivate: TYPE = RECORD [ ch, cw, dx, dy, ox, oy: INT _ 0, pds: ARRAY UsefulPsbIndex OF ProcessData _ ALL[[]] ]; ProcessData: TYPE = RECORD [ color: MyColor _ dormant, lastTill: MyTicks _ 0]; MyColor: TYPE = {active, recent, dormant}; MyTickIndex: CARDINAL = 16384; MyTicks: TYPE = INTEGER [0 .. MyTickIndex); microsecondsPerTick: LONG CARDINAL _ 16384; MicrosecondsToTicks: PROC [ms: LONG CARDINAL] RETURNS [mt: MyTicks] = { mt _ (ms/microsecondsPerTick) MOD MyTickIndex}; MyNowTicks: PROC RETURNS [now: MyTicks] = { now _ MicrosecondsToTicks[ BasicTime.PulsesToMicroseconds[ BasicTime.GetClockPulses[]]]; }; xor: Imager.Color = ImagerBackdoor.invert; CreateCmd: PROC [cmd: Commander.Handle] RETURNS [result: REF _ NIL, msg: ROPE _ NIL] --Commander.CommandProc-- = { [] _ CreateProcessWatcher[[name: "Process Watcher", iconic: FALSE]]; }; CreateProcessWatcher: PROC [viewerData: ViewerClasses.ViewerRec _ [], paint: BOOL _ TRUE] RETURNS [pwv: Viewer] = { pwv _ ViewerOps.CreateViewer[pwFlavor, viewerData, paint]; SetPWV[pwv]; }; pwFlavor: ATOM = $ProcessWatcher; pwClass: ViewerClasses.ViewerClass _ NEW [ViewerClasses.ViewerClassRec _ [ flavor: pwFlavor, paint: PaintProcessWatcher, init: InitProcessWatcher, destroy: DestroyProcessWatcher, tipTable: TIPUser.InstantiateNewTIPTable["ProcessWatcher.TIP"], notify: NotifyProcessWatcher ]]; rows: INT _ 16; cols: INT _ 16; gray: Imager.Color _ Imager.MakeGray[0.5]; lifetimeTicks: MyTicks _ MicrosecondsToTicks[1000000]; paintTicks: MyTicks _ MicrosecondsToTicks[300000]; doGray: BOOL _ TRUE; InitProcessWatcher: PROC [self: Viewer] --ViewerClasses.InitProc-- = { pw: ProcessWatcher = NEW [ProcessWatcherPrivate _ []]; self.data _ pw; }; DestroyProcessWatcher: PROC [self: Viewer] --ViewerClasses.DestroyProc-- = { SetPWV[NIL]; }; counts: REF Counts _ NEW [Counts _ ALL[0]]; Counts: TYPE = ARRAY MyColor OF INT; debug: BOOL _ FALSE; CARD: TYPE = LONG CARDINAL; PaintProcessWatcher: PROC [self: Viewer, context: Imager.Context, whatChanged: REF, clear: BOOL] RETURNS [quit: BOOL _ FALSE] --ViewerClasses.PaintProc-- = { pw: ProcessWatcher = NARROW[self.data]; now: MyTicks = MyNowTicks[]; later: MyTicks = (CARD[now] + lifetimeTicks) MOD MyTickIndex; paintAllowance: MyTicks = (CARD[now] + paintTicks) MOD MyTickIndex; IF painting THEN RETURN; painting _ TRUE; IF whatChanged = $Sample AND pw.ch = self.ch AND pw.cw = self.cw AND lastPaint < paintAllowance THEN { psbi: CARDINAL _ 0; lastPaint _ now; Imager.TranslateT[context, [pw.ox, pw.oy]]; FOR i: INT IN [0 .. rows) DO FOR j: INT IN [0 .. cols) DO ready: BOOL = displayedVectors[psbi]; pd: ProcessData = pw.pds[psbi]; PaintIt: PROC [color: Imager.Color, mc: MyColor] = INLINE { x: INT = j*pw.dx+1; y: INT = i*pw.dy+1; pw.pds[psbi].color _ mc; IF debug THEN { counts[mc] _ counts[mc] + 1; Imager.SetColor[context, ImagerBackdoor.invert]; Imager.MaskRectangle[context, [x, y, pw.dx-1, pw.dy-1]]; }; Imager.SetColor[context, color]; Imager.MaskRectangle[context, [x, y, pw.dx-1, pw.dy-1]]; }; IF ready THEN { IF pd.color # active THEN PaintIt[Imager.black, active]; pw.pds[psbi].lastTill _ later; } ELSE { SELECT TRUE FROM now > pd.lastTill => IF pd.color # dormant THEN PaintIt[Imager.white, dormant]; (pd.color # recent) AND doGray => PaintIt[gray, recent]; ENDCASE => NULL; }; psbi _ psbi + 1; ENDLOOP; ENDLOOP; } ELSE { psbi: CARDINAL _ 0; w, h: INT; lastPaint _ now; pw.ch _ self.ch; pw.cw _ self.cw; pw.dx _ pw.cw/cols; pw.dy _ pw.ch/rows; w _ pw.dx * cols; h _ pw.dy * rows; pw.ox _ (pw.cw - w)/2; pw.oy _ (pw.ch - h)/2; Imager.SetColor[context, Imager.white]; Imager.MaskRectangle[context, [0, 0, pw.cw, pw.ch]]; Imager.TranslateT[context, [pw.ox, pw.oy]]; Imager.SetColor[context, Imager.black]; FOR i: INT IN [0 .. rows] DO y: INT = i * pw.dy; Imager.MaskVector[context, [0, y], [w, y]]; ENDLOOP; FOR j: INT IN [0 .. cols] DO x: INT = j * pw.dx; Imager.MaskVector[context, [x, 0], [x, h]]; ENDLOOP; FOR i: INT IN [0 .. rows) DO FOR j: INT IN [0 .. cols) DO IF displayedVectors[psbi] THEN { Imager.MaskRectangle[context, [j*pw.dx+1, i*pw.dy+1, pw.dx-1, pw.dy-1]]; pw.pds[psbi].lastTill _ later; pw.pds[psbi].color _ active; } ELSE { pw.pds[psbi].lastTill _ 0; pw.pds[psbi].color _ dormant; }; psbi _ psbi + 1; ENDLOOP; ENDLOOP; }; painting _ FALSE; }; lastPaint: MyTicks _ 0; painting: BOOL _ FALSE; ReadPI: PROC RETURNS [pi: PsbIndex] = TRUSTED INLINE { pi _ PrincOpsUtils.PsbHandleToIndex[PrincOpsUtils.ReadPSB[]]}; NotifyProcessWatcher: PROC [self: Viewer, input: LIST OF REF ANY] --ViewerClasses.NotifyProc-- = { pw: ProcessWatcher = NARROW[self.data]; notifier: PsbIndex = ReadPI[]; who: UsefulPsbIndex _ 0; WHILE input # NIL DO WITH input.first SELECT FROM mc: TIPUser.TIPScreenCoords => { row: INT = (mc.mouseY - pw.oy) / pw.dy; col: INT = (mc.mouseX - pw.ox) / pw.dx; index: INT = row * cols + col; IF index IN UsefulPsbIndex THEN who _ index; input _ input.rest; }; a: ATOM => SELECT a FROM $Poke => { input _ input.rest; MessageWindow.Append[ message: IO.PutFR["Process %g (%bB, %xH)%g", [cardinal[who]], [cardinal[who]], [cardinal[who]], [rope[IF notifier = who THEN " --- the notifier!" ELSE NIL]]], clearFirst: TRUE]; }; ENDCASE => ERROR; ENDCASE => ERROR; ENDLOOP; }; me: ProcessWatch.Consumer = [ConsumeReadyList]; pwv: Viewer _ NIL; sample: CONDITION; notedVectors, displayedVectors: ProcessWatch.ReadyVector; SetPWV: ENTRY PROC [v: Viewer] = { diff: BOOL = (pwv = NIL) # (v = NIL); pwv _ v; IF diff THEN { IF pwv = NIL THEN ProcessWatch.RemoveConsumer[me] ELSE ProcessWatch.AddConsumer[me]; }; }; ConsumeReadyList: ENTRY PROC [REF ANY] = { IF ProcessWatch.readyVector # notedVectors THEN { notedVectors _ ProcessWatch.readyVector; BROADCAST sample; }; }; PaintIt: PROC = { Wait: ENTRY PROC RETURNS [v: Viewer] = { DO WAIT sample; displayedVectors _ notedVectors; IF pwv # NIL THEN RETURN [pwv]; ENDLOOP; }; DO ViewerOps.PaintViewer[Wait[], client, FALSE, $Sample]; ENDLOOP; }; Start: PROC = TRUSTED { ViewerOps.RegisterViewerClass[pwFlavor, pwClass]; Loader.MakeProcedureResident[ConsumeReadyList]; Process.InitializeCondition[@sample, 0]; Process.DisableTimeout[@sample]; Process.Detach[FORK PaintIt[]]; Commander.Register["ProcessWatcher", CreateCmd, "Create a Process Watcher"]; }; Start[]; }. HProcessWatchViewer.Mesa Spreitzer, March 26, 1986 11:55:36 am PST Κ»– "cedar" style˜code™K™)—K˜KšΟk œ/œq˜«K˜šΟnœœ˜!Kšœ/œQ˜‰—K˜Kšœ˜K˜Kšœœœ˜Kšœ œ˜#Kšœœ˜3Kšœœ˜$Kšœ œ˜-K˜Kšœœœ˜1šœœœ˜&Kšœœ˜ Kšœœœœ˜2K˜—K˜šœ œœ˜Kšœ˜K˜—K˜Kšœ œ˜*K˜Kšž œœ ˜Kšœ œœ˜+K˜Kšœœœ ˜+K˜š žœœœœœ˜GKšœœ˜/—K˜šž œœœ˜+KšœX˜XK˜—K˜K˜*K˜šž œœœ œœœœΟcœ˜rKšœ<œ˜DK˜—K˜š žœœ3œœœ˜sKšœ:˜:K˜ K˜—K˜Kšœ œ˜!K˜šœ%œ"˜JKšœ˜K˜K˜K˜K˜?K˜K˜—K˜Kšœœ˜Kšœœ˜K˜*Kšœ6˜6Kšœ2˜2Kšœœœ˜K˜šžœœŸœ˜FKšœœ˜6K˜K˜—K˜šžœœŸœ˜LKšœœ˜ K˜—K˜Kšœœ œ œ˜+Kš œœœ œœ˜$Kšœœœ˜K˜Kšœœœœ˜K˜šžœœ6œ œœœœŸœ˜Kšœœ ˜'Kšœ˜Kšœœœ ˜=Kšœœœ ˜CKšœ œœ˜Kšœ œ˜š œœœœœ˜fKšœœ˜K˜Kšœ+˜+šœœœ ˜šœœœ ˜Kšœœ˜%K˜šžœœ&œ˜;Kšœœ ˜Kšœœ ˜K˜šœœ˜K˜K˜0K˜8K˜—Kšœ ˜ K˜8K˜—šœœ˜Kšœœ˜8Kšœ˜K˜—šœ˜šœœ˜Kšœœœ ˜OKšœœ!˜8Kšœœ˜—K˜—K˜Kšœ˜—Kšœ˜—K˜—šœ˜Kšœœ˜Kšœœ˜ K˜K˜K˜K˜K˜K˜K˜K˜K˜K˜'K˜4Kšœ+˜+K˜'šœœœ ˜Kšœœ ˜K˜+Kšœ˜—šœœœ ˜Kšœœ ˜K˜+Kšœ˜—šœœœ ˜šœœœ ˜šœœ˜ K˜HKšœ˜Kšœ˜K˜—šœ˜Kšœ˜Kšœ˜K˜—K˜Kšœ˜—Kšœ˜—K˜—Kšœ œ˜K˜K˜Kšœ œœ˜—K˜š žœœœœœ˜6Kšœ>˜>—K˜šžœœœœœœŸœ˜bKšœœ ˜'Kšœ˜Kšœ˜šœ œ˜šœ œ˜šœ ˜ Kšœœ˜'Kšœœ˜'Kšœœ˜Kšœœœ ˜,K˜K˜—šœœœ˜˜ K˜šœ˜Kš œ œ[œœœœ˜žKšœ œ˜—K˜—Kšœœ˜—Kšœœ˜—Kšœ˜—K˜—K˜Kšœ/˜/Kšœœ˜Kšœ œ˜Kšœ9˜9K˜šžœœœ˜"Kšœœ œ œ˜%Kšœ˜šœœ˜Kšœœœ!œ˜TK˜—K˜—K˜š žœœœœœ˜*šœ)œ˜1Kšœ(˜(Kš œ˜Kšœ˜—K˜—K˜šžœœ˜šžœœœœ˜(š˜Kšœ˜ Kšœ ˜ Kšœœœœ˜Kšœ˜—K˜—š˜Kšœ&œ ˜6Kšœ˜—K˜—K˜šžœœœ˜Kšœ1˜1Kšœ/˜/K˜(Kšœ ˜ Kšœœ ˜K˜LK˜—K˜K˜K˜K˜—…—Ξ#Ρ