ImagerCacheImpl.mesa
Copyright © 1985 by Xerox Corporation. All rights reserved.
Michael Plass, June 25, 1985 1:14:57 pm PDT
Doug Wyatt, November 27, 1985 5:22:56 pm PST
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];
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: BOOL ← FALSE] ~ {Flush[NARROW[val]]};
[] ← RefTab.Pairs[cacheTab, epa];
maxProbes ← newProbeLimit;
};
CharMaskSize: PROC [c: CharMask] RETURNS [CARDINAL] ~ TRUSTED {
WITH c: c SELECT FROM
raster => RETURN[SIZE[CharMaskRep.raster[c.sSizeBB*((c.fSizeBB+15)/16)]]];
runs => RETURN[SIZE[CharMaskRep.runs[c.nRuns]]];
uncached => RETURN[SIZE[CharMaskRep.uncached]];
ENDCASE => ERROR;
};
SaveOnStream: ENTRY PROC [x: Ref, stream: IO.STREAM] ~ {
FOR i: INT IN [0..x.maxSize) DO
c: CharMask ~ x[i];
IF c#NIL THEN {
size: CARDINAL ~ CharMaskSize[c];
c.ref ← NIL;
};
ENDLOOP;
};
SaveOnFile: PUBLIC PROC [x: Ref, fileName: ROPE] ~ {
stream: IO.STREAM ~ FS.StreamOpen[fileName: fileName, accessOptions: $create];
SaveOnStream[x, stream];
IO.Close[stream];
};
RestoreFromFile: PUBLIC PROC [x: Ref, fileName: ROPE] ~ {
};
END.