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: INTFIRST[INT];
lastFile: ROPENIL;
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: BOOLTRUE]--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.