ImagerCacheImpl.mesa
Copyright © 1985 by Xerox Corporation. All rights reserved.
Michael Plass, June 25, 1985 1:14:57 pm PDT
Doug Wyatt, May 20, 1985 11:40:49 am PDT
DIRECTORY
Basics USING [BITAND, BITSHIFT, BITXOR],
Checksum USING [ComputeChecksum],
ImagerCache USING [],
ImagerDevice USING [CharMask],
ImagerFont USING [XChar],
RefTab USING [Create, Fetch, Pairs, Ref, Store];
ImagerCacheImpl: CEDAR MONITOR LOCKS x USING x: Ref
IMPORTS Basics, Checksum, RefTab
EXPORTS ImagerCache
~ BEGIN
CharMask: TYPE ~ ImagerDevice.CharMask;
XChar: TYPE ~ ImagerFont.XChar;
Ref: TYPE ~ REF Rep;
Rep: PUBLIC TYPE ~ MONITORED RECORD [
size: NAT,
lgMaxSize: NAT,
stuffCount: LONG CARDINAL ← 0,
seq: SEQUENCE maxSize: CARDINAL OF CharMask
];
Create: PUBLIC PROC [size: NAT] RETURNS [new: Ref] ~ {
maxSize: CARDINAL ← 1;
lgMaxSize: NAT ← 0;
UNTIL maxSize > size DO
maxSize ← 2*maxSize;
lgMaxSize ← lgMaxSize + 1;
ENDLOOP;
new ← NEW[Rep[maxSize]];
new.size ← 0;
new.lgMaxSize ← lgMaxSize;
};
Size: PUBLIC ENTRY PROC [x: Ref] RETURNS [NAT] ~ {
RETURN [x.size];
};
CharAndFont: TYPE ~ MACHINE DEPENDENT RECORD [char: XChar, font: REF];
maxProbes: NAT ← 15;
Fetch: PUBLIC ENTRY PROC [x: Ref, font: REF, char: XChar] RETURNS [CharMask] ~ TRUSTED {
last: CARDINAL ~ x.maxSize-1;
cf: CharAndFont ← [char, font];
cksum: CARDINAL ~ Checksum.ComputeChecksum[nWords: SIZE[CharAndFont], p: @cf];
hash: CARDINAL ← Basics.BITAND[last, Basics.BITXOR[cksum, Basics.BITSHIFT[cksum, -x.lgMaxSize]]];
probes: CARDINAL ← 0;
c: CharMask ← NIL;
UNTIL (c ← x[hash])=NIL OR (c.font=font AND c.char=char) DO
probes ← probes + 1;
IF probes < maxProbes THEN {
IF hash#0 THEN hash ← hash-1 ELSE hash ← last;
}
ELSE RETURN [NIL];
ENDLOOP;
RETURN [c];
};
Store: PUBLIC ENTRY PROC [x: Ref, charMask: CharMask] RETURNS [ok: BOOL] ~ TRUSTED {
last: CARDINAL ~ x.maxSize-1;
cf: CharAndFont ← [charMask.char, charMask.font];
cksum: CARDINAL ~ Checksum.ComputeChecksum[nWords: SIZE[CharAndFont], p: @cf];
hash: CARDINAL ← Basics.BITAND[last, Basics.BITXOR[cksum, Basics.BITSHIFT[cksum, -x.lgMaxSize]]];
probes: CARDINAL ← 0;
c: CharMask ← NIL;
UNTIL (c ← x[hash])=NIL OR (c.font=cf.font AND c.char=cf.char) DO
probes ← probes + 1;
IF probes < maxProbes THEN {
IF hash#0 THEN hash ← hash-1 ELSE hash ← last;
}
ELSE {
Replace an entry - this is a cache!
x[hash] ← charMask;
x.stuffCount ← x.stuffCount + 1;
};
ENDLOOP;
IF c = NIL AND x.size < x.maxSize THEN {
x.size ← x.size + 1;
c ← x[hash] ← charMask;
};
RETURN [c # NIL];
};
Flush: PUBLIC ENTRY PROC [x: Ref] ~ {
FOR i: INT IN [0..x.maxSize) DO
x[i] ← NIL;
ENDLOOP;
x.size ← 0;
};
GetList: PUBLIC ENTRY PROC [x: Ref] RETURNS [list: LIST OF CharMask ← NIL] ~ {
FOR i: INT IN [0..x.maxSize) DO
c: CharMask ← x[i];
IF c#NIL THEN list ← CONS[c, list];
ENDLOOP;
};
GetNamedCache: PUBLIC PROC [atom: ATOM, createSize: NAT] RETURNS [r: Ref] ~ {
r ← NARROW[RefTab.Fetch[cacheTab, atom].val];
IF r = NIL OR r.maxSize < createSize THEN {
IF r # NIL THEN Flush[r];
r ← Create[createSize];
[] ← RefTab.Store[cacheTab, atom, r];
};
};
cacheTab: RefTab.Ref ~ RefTab.Create[];
FlushAll: PROC [newProbeLimit: NAT ← 15] ~ {
epa: PROC [key, val: REF] RETURNS [quit: BOOLFALSE] ~ {Flush[NARROW[val]]};
[] ← RefTab.Pairs[cacheTab, epa];
maxProbes ← newProbeLimit;
};
END.