DIRECTORY Commander, CommanderOps, Convert, IO, Labels, Process, Real, RefText, Rope, ViewerClasses; ThreadsCountLabel: CEDAR PROGRAM IMPORTS Commander, CommanderOps, Convert, IO, Labels, Process, Real, RefText, Rope = BEGIN ROPE: TYPE ~ Rope.ROPE; Viewer: TYPE ~ ViewerClasses.Viewer; CirioNubThreadDataRep: TYPE ~ MACHINE DEPENDENT RECORD [ --translated from CirioNubTypes.h index, gen: CARD, sStat: CARD, pri: CARD, dbMsg: INT, dbFrozen: INT, pc, sp, fp: POINTER]; Counts: TYPE ~ RECORD [f, ry, rn, m, c, o: NAT ¬ 0]; Style: TYPE ~ {twiddle, count}; pause: INT ¬ 15000; style: Style ¬ twiddle; divisor: NAT ¬ 1; nThreads: INT ¬ 121; buf: REF TEXT ¬ RefText.New[100]; twiddle: ARRAY [0..3] OF CHAR ¬ ['\\, '|, '/, '-]; hexChars: ARRAY [0..15] OF CHAR ~ ['0, '1, '2, '3, '4, '5, '6, '7, '8, '9, 'A, 'B, 'C, 'D, 'E, 'F]; LocalGetThread: UNSAFE PROC [idx: INT, buf: POINTER TO CirioNubThreadDataRep] RETURNS [INT] ~ UNCHECKED MACHINE CODE {"CirioNubLocalGetThread"}; GetMaxThreads: PROC RETURNS [INT] ~ TRUSTED MACHINE CODE {"CirioNubLocalGetMaxThreads"}; Watch: PROC [but: Viewer] ~ { twid: [0..255] ¬ 0; rem: NAT ¬ divisor; Process.SetPriority[Process.priorityForeground]; DO counts: Counts ¬ []; buf: CirioNubThreadDataRep; desc: ROPE; nThreads ¬ GetMaxThreads[]; FOR idx: NAT IN [0..nThreads) DO cc: INT; TRUSTED {cc ¬ LocalGetThread[idx, @buf]}; IF cc#0 THEN counts.f ¬ counts.f.SUCC ELSE SELECT buf.sStat FROM 1 => counts.f ¬ counts.f.SUCC; 2 => counts.ry ¬ counts.ry.SUCC; 3 => counts.rn ¬ counts.rn.SUCC; 4 => counts.m ¬ counts.m.SUCC; 5 => counts.c ¬ counts.c.SUCC; ENDCASE => counts.o ¬ counts.o.SUCC; ENDLOOP; IF (rem ¬ rem.PRED) = 0 THEN { desc ¬ FmtCounts[counts, style, twid]; Labels.Set[but, desc]; rem ¬ divisor}; Process.PauseMsec[pause]; twid ¬ (twid.SUCC) MOD 256; ENDLOOP; }; Control: PROC [cmd: Commander.Handle] RETURNS [result: REF ANY ¬ NIL, msg: ROPE ¬ NIL] ~ { argv: CommanderOps.ArgumentVector ~ CommanderOps.Parse[cmd]; i: NAT ¬ 1; WHILE i < argv.argc DO len: INT ~ argv[i].Length; SELECT TRUE FROM len = 0 => RETURN [$Failure, usage]; argv[i].Fetch[len-1]='s => { rl: ROPE ~ argv[i].Substr[len: len-1]; period: REAL ¬ 0.0; period ¬ Convert.RealFromRope[rl !Convert.Error => { cmd.err.PutF["Convert.Error near %g trying to parse \"%q\" as a REAL.\n", [integer[index]], [rope[rl]] ]; GOTO Dont}]; IF period < 0.1 OR period > 1.0E3 THEN RETURN [$Failure, IO.PutFR1["Sample period should be in the range [0.1 .. 1000] seconds, not %g", [real[period]] ]]; pause ¬ Real.Round[period*1000]; cmd.out.PutF1["Sampling period set to %g seconds.\n", [real[period]] ]; EXITS Dont => i¬i}; argv[i].Fetch[0] = '/ => { ri: ROPE ~ argv[i].Substr[start: 1]; d: INT ~ Convert.IntFromRope[ri !Convert.Error => { cmd.err.PutF["Convert.Error near %g trying to parse \"%q\" as an INT.\n", [integer[index]], [rope[ri]] ]; GOTO Dont}]; IF d<1 OR d>65536 THEN RETURN [$Failure, IO.PutFR1["Painting divisor should be in the range [1 .. 65536], not %g", [integer[d]] ]]; divisor ¬ d; cmd.out.PutF1["Painting divisor set to %g.\n", [integer[d]] ]; EXITS Dont => i¬i}; argv[i].Equal["twiddle", FALSE] => style ¬ twiddle; argv[i].Equal["count", FALSE] => style ¬ count; ENDCASE => RETURN [$Failure, usage]; i ¬ i.SUCC; ENDLOOP; RETURN}; FmtCounts: PROC [counts: Counts, style: Style, it: [0..255]] RETURNS [ROPE] ~ { buf.length ¬ 0; buf ¬ RefText.AppendChar[buf, 'f]; buf ¬ Convert.AppendCard[buf, counts.f]; buf ¬ RefText.AppendRope[buf, " ry"]; buf ¬ Convert.AppendCard[buf, counts.ry]; buf ¬ RefText.AppendRope[buf, " rn"]; buf ¬ Convert.AppendCard[buf, counts.rn]; buf ¬ RefText.AppendRope[buf, " m"]; buf ¬ Convert.AppendCard[buf, counts.m]; buf ¬ RefText.AppendRope[buf, " c"]; buf ¬ Convert.AppendCard[buf, counts.c]; buf ¬ RefText.AppendRope[buf, " o"]; buf ¬ Convert.AppendCard[buf, counts.o]; buf ¬ RefText.AppendChar[buf, ' ]; SELECT style FROM twiddle => buf ¬ RefText.AppendChar[buf, twiddle[it MOD 4]]; count => { buf ¬ RefText.AppendChar[buf, hexChars[it/16]]; buf ¬ RefText.AppendChar[buf, hexChars[it MOD 16]]}; ENDCASE => ERROR; RETURN Rope.FromRefText[buf]}; usage: ROPE ~ "Usage: ThreadsCountLabel ( twiddle | count | s | /)*"; Start: PROC ~ { n0: ROPE ~ FmtCounts[[f: 22, rn: 12, m: 13], count, 255]; lab: Viewer ~ Labels.Create[[name: n0]]; TRUSTED {Process.Detach[FORK Watch[lab]]}; Commander.Register["ThreadsCountLabel", Control, usage]; RETURN}; Start[]; END. ¬ ThreadsCountLabel.mesa Copyright Σ 1990, 1992 by Xerox Corporation. All rights reserved. Spreitze, November 5, 1990 10:14 am PST Weiser, May 26, 1992 10:08 pm PDT Κ8•NewlineDelimiter –(cedarcode) style™codešœ™Kšœ Οeœ7™BK™'K™!—K˜KšΟk œ#žœ6˜dK˜šΟnœžœž˜ Kšžœ#žœ&˜RK˜—K˜Kšž˜K˜Kšžœžœžœ˜Kšœžœ˜$K˜š œžœžœž œžœΟc!˜ZKšœ žœ˜Kšœžœ˜ Kšœžœ˜ Kšœžœ˜ Kšœ žœ˜Kšœ žœ˜—K˜Kšœžœžœžœ˜4Kšœžœ˜K˜Kšœžœ ˜K˜Kšœ žœ˜Kšœ žœ˜Kšœžœžœ˜!Kšœ žœžœžœ˜2Kšœ žœ žœžœD˜cK˜šŸœžœžœžœžœžœžœžœ˜[Kšœž œžœžœ˜4—K˜šŸ œžœžœžœ˜!Kšœžœžœžœ ˜6—K˜šŸœžœ˜K˜Kšœžœ ˜Kšœ0˜0šž˜K˜K˜Kšœžœ˜ K˜šžœžœžœž˜ Kšœžœ˜Kšžœ"˜)Kšžœžœž˜%šžœžœ ž˜Kšœžœ˜Kšœžœ˜ Kšœžœ˜ Kšœžœ˜Kšœžœ˜Kšžœžœ˜$—Kšžœ˜—šžœ žœžœ˜K˜&K˜K˜—K˜Kšœ žœžœ˜Kšžœ˜—K˜—K˜šŸœžœžœ žœžœžœžœžœ˜ZK˜Kšžœ˜—Kšœžœ˜3Kšœžœ˜/Kšžœžœ˜$—Kšœžœ˜ Kšžœ˜—Kšžœ˜—K˜šŸ œžœ.žœžœ˜OK˜K˜"K˜(K˜%K˜)K˜%K˜)K˜$K˜(K˜$K˜(K˜$K˜(K˜"šžœž˜Kšœ4žœ˜<˜ K˜/Kšœ*žœ˜4—Kšžœžœ˜—Kšžœ˜—K˜KšœžœH˜SK˜šŸœžœ˜Kšœžœ1˜9K˜(Kšžœžœ˜*K˜8Kšžœ˜—K˜K˜K˜Kšžœ˜—…—>"