ImagerCacheImpl.mesa
Copyright © 1985 by Xerox Corporation. All rights reserved.
Michael Plass, May 17, 1985 6:30:31 pm PDT
DIRECTORY
Basics,
Checksum,
ImagerCache,
ImagerDev USING [CharMask],
ImagerFont USING [XChar],
Real,
RefTab;
ImagerCacheImpl: CEDAR MONITOR LOCKS x USING x: Ref
IMPORTS Basics, Checksum, Real, RefTab
EXPORTS ImagerCache
~ BEGIN
CharMask: TYPE ~ ImagerDev.CharMask;
XChar: TYPE ~ ImagerFont.XChar;
Ref: TYPE ~ REF Rep;
Rep: PUBLIC TYPE ~ MONITORED RECORD [
size: NAT,
limit: NAT,
lgMaxSize: NAT,
seq: SEQUENCE maxSize: CARDINAL OF CharMask
];
maxLoad: REAL ← 0.9;
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;
new.limit ← MIN[Real.Round[maxSize*maxLoad], maxSize-1];
};
Size: PUBLIC ENTRY PROC [x: Ref] RETURNS [NAT] ~ {
RETURN [x.size];
};
CharAndFont: TYPE ~ MACHINE DEPENDENT RECORD [char: XChar, font: REF];
Fetch: PUBLIC ENTRY PROC [x: Ref, font: REF, char: XChar] RETURNS [c: CharMask] ~ TRUSTED {
last: CARDINAL ~ x.maxSize-1;
cf: CharAndFont ← [char, font];
hash: CARDINAL ← Checksum.ComputeChecksum[nWords: SIZE[CharAndFont], p: @cf];
hash ← Basics.BITAND[last, Basics.BITXOR[hash, Basics.BITSHIFT[hash, -x.lgMaxSize]]];
UNTIL (c ← x[hash])=NIL OR (c.font=font AND c.char=char) DO
must exit sometime because the table is never completely filled.
IF hash = 0 THEN hash ← hash-1 ELSE hash ← last;
ENDLOOP;
};
Store: PUBLIC ENTRY PROC [x: Ref, charMask: CharMask] RETURNS [ok: BOOL] ~ TRUSTED {
last: CARDINAL ~ x.maxSize-1;
cf: CharAndFont ← [charMask.char, charMask.font];
hash: CARDINAL ← Checksum.ComputeChecksum[nWords: SIZE[CharAndFont], p: @cf];
c: CharMask;
hash ← Basics.BITAND[last, Basics.BITXOR[hash, Basics.BITSHIFT[hash, -x.lgMaxSize]]];
UNTIL (c ← x[hash])=NIL OR (c.font=cf.font AND c.char=cf.char) DO
must exit sometime because the table is never completely filled.
IF hash = 0 THEN hash ← hash-1 ELSE hash ← last;
ENDLOOP;
IF c = NIL AND x.size >= x.limit THEN RETURN [ok: FALSE];
IF c = NIL THEN x.size ← x.size + 1;
x[hash] ← charMask;
RETURN [ok: TRUE];
};
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 THEN {
r ← Create[createSize];
IF NOT RefTab.Insert[cacheTab, atom, r] THEN {
We lost a race: defer to the winner.
r ← NARROW[RefTab.Fetch[cacheTab, atom].val];
};
};
};
cacheTab: RefTab.Ref ~ RefTab.Create[];
END.