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