ProcessWatchViewer.Mesa
Spreitzer, March 26, 1986 11:55:36 am PST
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: REFNIL, msg: ROPENIL] --Commander.CommandProc-- = {
[] ← CreateProcessWatcher[[name: "Process Watcher", iconic: FALSE]];
};
CreateProcessWatcher: PROC [viewerData: ViewerClasses.ViewerRec ← [], paint: BOOLTRUE] 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: BOOLTRUE;
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: BOOLFALSE;
CARD: TYPE = LONG CARDINAL;
PaintProcessWatcher: PROC [self: Viewer, context: Imager.Context, whatChanged: REF, clear: BOOL] RETURNS [quit: BOOLFALSE] --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: BOOLFALSE;
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[];
}.