ProcessWatchInstantaneously.Mesa
Spreitzer, April 22, 1986 6:12:06 pm PST
DIRECTORY BasicTime, Commander, Icons, Imager, ImagerBackdoor, ImagerColor, IO, MessageWindow, PrincOps, PrincOpsUtils, Process, ProcessWatch, ProcessWatchPrinting, Real, RealFns, Rope, TIPUser, ViewerClasses, ViewerOps;
ProcessWatchInstantaneously:
CEDAR
MONITOR
IMPORTS BasicTime, Commander, Icons, Imager, ImagerBackdoor, ImagerColor, IO, MessageWindow, PrincOpsUtils, Process, ProcessWatch, ProcessWatchPrinting, Real, RealFns, TIPUser, ViewerOps
= {
ROPE: TYPE = Rope.ROPE;
PsbIndex: TYPE = PrincOps.PsbIndex;
UsefulPsbIndex: TYPE = ProcessWatch.UsefulPsbIndex;
nUsefulPsbs: CARDINAL = ProcessWatch.nUsefulPsbs;
Viewer: TYPE = ViewerClasses.Viewer;
ReadyVector: TYPE = ProcessWatch.ReadyVector;
ProcessWatcher: TYPE = REF ProcessWatcherPrivate;
ProcessWatcherPrivate:
TYPE =
RECORD [
ch, cw, rows, cols, lastFullColumn, width, height, dx, dy, ox, oy: INT ← 0,
pds: ARRAY UsefulPsbIndex OF ProcessData ← ALL[[]]
];
ProcessData:
TYPE =
RECORD [
color: MyColor ← dormant,
lastTill: BasicTime.Pulses ← 0];
MyColor: TYPE = {active, recent, past, old, dormant};
colorCode:
ARRAY MyColor
OF Imager.ConstantColor ← [
active: Imager.white,
recent: ImagerColor.ColorFromRGB[[1.0, 1.0, 0]],
past: ImagerColor.ColorFromRGB[[1.0, 0, 0]],
old: ImagerColor.ColorFromRGB[[0.25, 0, 0.25]],
dormant: Imager.black
];
xor: Imager.Color = ImagerBackdoor.invert;
Million: LONG CARDINAL = 1000000;
DecayingColor: TYPE = MyColor[recent .. old];
colorPersistance:
ARRAY DecayingColor
OF BasicTime.Pulses ← [
recent: BasicTime.MicrosecondsToPulses[666*Million/10],
past: BasicTime.MicrosecondsToPulses[66*Million],
old: BasicTime.MicrosecondsToPulses[60*Million]
];
CreateCmd:
PROC [cmd: Commander.Handle]
RETURNS [result:
REF ←
NIL, msg:
ROPE ←
NIL]
--Commander.CommandProc-- = {
[] ← CreateProcessWatcher[[name: "Instantaneous Process Watcher"]];
};
CreateProcessWatcher:
PROC [viewerData: ViewerClasses.ViewerRec ← [], paint:
BOOL ←
TRUE]
RETURNS [pwv: Viewer] = {
pwv ← ViewerOps.CreateViewer[pwFlavor, viewerData, paint];
SetPWV[pwv];
};
pwFlavor: ATOM = $InstantaneousProcessWatcher;
pwClass: ViewerClasses.ViewerClass ←
NEW [ViewerClasses.ViewerClassRec ← [
flavor: pwFlavor,
paint: PaintProcessWatcher,
init: InitProcessWatcher,
destroy: DestroyProcessWatcher,
tipTable: TIPUser.InstantiateNewTIPTable["ProcessWatcher.TIP"],
notify: NotifyProcessWatcher,
icon: Icons.NewIconFromFile["ProcessWatcher.icons", 0]
]];
gray: Imager.Color ← Imager.MakeGray[0.5];
lifetime: BasicTime.Pulses ← BasicTime.MicrosecondsToPulses[1000000];
paintTime: BasicTime.Pulses ← BasicTime.MicrosecondsToPulses[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-- = {
ENABLE UNWIND => painting ← FALSE;
pw: ProcessWatcher = NARROW[self.data];
now: BasicTime.Pulses = BasicTime.GetClockPulses[];
paintAllowance: BasicTime.Pulses = now + paintTime;
laters: ARRAY DecayingColor OF BasicTime.Pulses;
latest: BasicTime.Pulses;
reset: BOOL = lastPaint >= paintAllowance;
FOR dc: DecayingColor
IN DecayingColor
DO
laters[dc] ← now + colorPersistance[dc];
ENDLOOP;
latest ← laters[FIRST[DecayingColor]];
IF painting THEN RETURN;
painting ← TRUE;
IF whatChanged # $Sample
OR pw.ch # self.ch
OR pw.cw # self.cw
OR reset
THEN {
lastPaint ← now;
pw.ch ← self.ch;
pw.cw ← self.cw;
FOR side:
INT ← Real.Fix[RealFns.SqRt[
REAL[pw.ch]*
REAL[pw.cw]]], side - 1
DO
IF side = 0 THEN {pw.rows ← pw.cols ← 16; EXIT};
pw.rows ← pw.ch/side;
pw.cols ← pw.cw/side;
WHILE (pw.rows-1) * pw.cols >= nUsefulPsbs
DO
pw.rows ← pw.rows - 1;
ENDLOOP;
WHILE (pw.cols-1) * pw.rows >= nUsefulPsbs
DO
pw.cols ← pw.cols - 1;
ENDLOOP;
IF pw.rows * pw.cols >= nUsefulPsbs THEN EXIT;
ENDLOOP;
pw.lastFullColumn ← nUsefulPsbs - (pw.rows-1)*pw.cols;
pw.dx ← pw.cw / pw.cols;
pw.dy ← pw.ch / pw.rows;
pw.width ← pw.dx * pw.cols;
pw.height ← pw.dy * pw.rows;
pw.ox ← (pw.cw - pw.width)/2;
pw.oy ← (pw.ch - pw.height)/2;
Imager.SetColor[context, colorCode[dormant]];
Imager.MaskRectangle[context, [0, 0, pw.cw, pw.ch]];
Imager.TranslateT[context, [pw.ox, pw.oy]];
Imager.SetColor[context, colorCode[active]];
FOR row:
INT
IN [0 .. pw.rows]
DO
y: INT = row * pw.dy;
w: INT = IF row = pw.rows THEN pw.lastFullColumn*pw.dx ELSE pw.width;
Imager.MaskVector[context, [0, y], [w, y]];
ENDLOOP;
FOR col:
INT
IN [0 .. pw.cols]
DO
x: INT = col * pw.dx;
h: INT = IF col > pw.lastFullColumn THEN pw.height-pw.dy ELSE pw.height;
Imager.MaskVector[context, [x, 0], [x, h]];
ENDLOOP;
FOR psbi: UsefulPsbIndex
IN UsefulPsbIndex
DO
IF reset THEN pw.pds[psbi].lastTill ← 0;
pw.pds[psbi].color ← dormant;
ENDLOOP;
}
ELSE Imager.TranslateT[context, [pw.ox, pw.oy]];
--now paint incrementally:--{
row, col: NAT ← 0;
lastPaint ← now;
FOR psbi: UsefulPsbIndex
IN UsefulPsbIndex
DO
ready: BOOL = displayedVectors[psbi];
pd: ProcessData = pw.pds[psbi];
PaintIt:
PROC [mc: MyColor] =
INLINE {
x: INT = col*pw.dx+1;
y: INT = row*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, colorCode[mc]];
Imager.MaskRectangle[context, [x, y, pw.dx-1, pw.dy-1]];
};
IF ready
THEN {
IF pd.color # active THEN PaintIt[active];
pw.pds[psbi].lastTill ← latest;
}
ELSE {
rightColor: MyColor ← dormant;
IF pd.lastTill > now
THEN
FOR dc: DecayingColor
DECREASING
IN DecayingColor
DO
IF pd.lastTill <= laters[dc]
THEN {
rightColor ← dc; EXIT;
};
ENDLOOP;
IF pd.color # rightColor THEN PaintIt[rightColor];
};
IF (col ← col + 1) = pw.cols THEN {col ← 0; row ← row + 1};
ENDLOOP;
};
painting ← FALSE;
};
lastPaint: BasicTime.Pulses ← 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;
valid: BOOL ← FALSE;
WHILE input #
NIL
DO
first: REF ANY = input.first;
input ← input.rest;
WITH first
SELECT
FROM
mc: TIPUser.TIPScreenCoords => {
y: INT = mc.mouseY - pw.oy;
x: INT = mc.mouseX - pw.ox;
row: INT = y / pw.dy;
col: INT = x / pw.dx;
index: INT = row * pw.cols + col;
valid ← y IN [0 .. pw.height) AND x IN [0 .. pw.width) AND (NOT (y >= pw.height - pw.dy AND x >= pw.lastFullColumn*pw.dx));
IF valid THEN who ← index;
};
a:
ATOM =>
SELECT a
FROM
$Select => {
MessageWindow.Append[
message:
IF valid
THEN IO.PutFR["Process %g (%bB, %xH)%g", [cardinal[who]], [cardinal[who]], [cardinal[who]], [rope[IF notifier = who THEN " --- the notifier!" ELSE NIL]]]
ELSE "Out of range",
clearFirst: TRUE];
};
$ShowTop => {
IF valid THEN TRUSTED {Process.Detach[FORK ProcessWatchPrinting.ShowTop[who]]};
};
$ShowStack => {
IF valid THEN TRUSTED {Process.Detach[FORK ProcessWatchPrinting.ShowStack[who]]};
};
$Unselect => NULL;
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] = {
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];
Process.InitializeCondition[@sample, 0];
Process.DisableTimeout[@sample];
Process.Detach[FORK PaintIt[]];
Commander.Register["InstantaneousProcessWatcher", CreateCmd, "Create an Instantaneous Process Watcher"];
};
Start[];
}.