DocCacheImpl.mesa
Mike Spreitzer August 5, 1986 1:11:00 am PDT
DIRECTORY Basics, DocCache, FS, HashTable, PutGet, RedBlackTree, Rope, TiogaOps, ViewerClasses, ViewerOps;
DocCacheImpl:
CEDAR
MONITOR
IMPORTS FS, HashTable, PutGet, RedBlackTree, Rope, TiogaOps, ViewerOps
EXPORTS DocCache
=
BEGIN OPEN DocCache;
byRef: RedBlackTree.Table = RedBlackTree.Create[GetRef, CompareRef];
byName: HashTable.Table = HashTable.Create[equal: HashTable.RopeEqualModCase, hash: HashTable.HashRopeModCase];
lastRef: INT ← FIRST[INT];
lastFile: ROPE ← NIL;
lastDoc: TiogaNode ← NIL;
cacheLimit: NAT ← 10;
GetRef:
PROC [data:
REF
ANY]
RETURNS [key:
REF
INT]
--RedBlackTree.GetKey-- = {
e: Entry = NARROW[data];
key ← e.ref;
};
CompareRef:
PROC [k, data:
REF
ANY]
RETURNS [c: Basics.Comparison]
--RedBlackTree.Compare-- = {
k1: REF INT = NARROW[k];
k2: REF INT = GetRef[data];
c ←
SELECT k1^
FROM
< k2^ => less,
= k2^ => equal,
> k2^ => greater,
ENDCASE => ERROR;
};
Entry: TYPE = REF EntryPrivate;
EntryPrivate:
TYPE =
RECORD [
fullFileName: ROPE,
doc: TiogaNode,
ref: REF INT
];
GetDoc:
PUBLIC
PROC [fileName:
ROPE]
RETURNS [doc: TiogaNode] = {
ENABLE FS.Error => {doc ← NIL; CONTINUE};
fullFileName: ROPE = IF FS.ExpandName[fileName].cp.ver.length = 0 THEN FS.FileInfo[fileName].fullFName ELSE fileName;
Search:
PROC [v: ViewerClasses.Viewer]
RETURNS [continue:
BOOL ←
TRUE]
--ViewerOps.EnumProc-- = {
IF v.file.Equal[fullFileName,
FALSE]
AND v.class.flavor = $Text
THEN {
tor: TiogaOps.Ref = TiogaOps.ViewerDoc[v];
IF tor #
NIL
THEN {
TRUSTED {doc ← LOOPHOLE[tor]};
continue ← FALSE;
};
};
};
GetFromCache:
ENTRY
PROC = {
ENABLE
UNWIND => {
byRef.DestroyTable[];
byName.Erase[];
lastRef ← FIRST[INT]};
e: Entry;
IF fullFileName.Equal[lastFile, FALSE] THEN {doc ← lastDoc; RETURN};
e ← NARROW[byName.Fetch[fullFileName].value];
IF e =
NIL
THEN {
doc ← PutGet.FromFile[fullFileName];
e ←
NEW [EntryPrivate ← [
fullFileName,
doc,
NEW [INT ← lastRef ← lastRef + 1]
]];
WHILE byRef.Size[] >= cacheLimit
DO
lru: Entry = NARROW[byRef.LookupSmallest[]];
[] ← byRef.Delete[lru.ref];
[] ← byName.Delete[lru.fullFileName];
ENDLOOP;
IF NOT byName.Insert[fullFileName, e] THEN ERROR;
byRef.Insert[e, e.ref];
}
ELSE {
doc ← e.doc;
[] ← byRef.Delete[e.ref];
e.ref^ ← lastRef ← lastRef + 1;
byRef.Insert[e, e.ref];
};
lastFile ← fullFileName;
lastDoc ← doc;
};
doc ← NIL;
ViewerOps.EnumerateViewers[Search];
IF doc # NIL THEN RETURN;
GetFromCache[];
};
END.