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
];
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.