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:
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[];
}.