-- RTTCache.mesa
-- Russ Atkinson, June 24, 1982 3:34 pm
-- Paul Rovner, May 31, 1983 12:32 pm

DIRECTORY
Rope USING [ROPE],
SafeStorage USING [nullType, Type];

RTTCache: CEDAR DEFINITIONS
= BEGIN OPEN Rope, SafeStorage;

ProcKey: TYPE = PROC ANY RETURNS ANY;
InvalidIndex: ERROR;

IntEntry: TYPE = REF IntEntryRep;
IntEntryRep: TYPE = RECORD
[next: IntEntry ← NIL,
valid: BOOLFALSE,
type: Type ← nullType,
proc: ProcKey ← NIL,
int: INT ← -1];

RefEntry: TYPE = REF RefEntryRep;
RefEntryRep: TYPE = RECORD
[next: RefEntry ← NIL,
valid: BOOLFALSE,
type: Type ← nullType,
proc: ProcKey ← NIL,
ref: REFNIL];

ComponentMap: TYPE = REF ComponentMapRep;
ComponentMapRep: TYPE = RECORD
[filledTypes, filledNames: CARDINAL ← 0,
comps: SEQUENCE len: CARDINAL OF ComponentEntry];
ComponentEntry: TYPE = RECORD
[validType, validName: BOOLFALSE,
type: Type ← nullType,
name: ROPENIL];
NullComponentEntry: ComponentEntry = [FALSE, FALSE, nullType, NIL];

LookupInt: PROC
[type: Type, proc: ProcKey] RETURNS [entry: IntEntry];
-- looks up the entry corresponding to the type and proc
-- entry.valid => entry.int is OK

FillIntEntry: PROC
[entry: IntEntry, value: INT] RETURNS [alreadyFull: BOOL];
-- fills the entry acquired by LookupInt
-- will not overwrite an already full entry

ClearIntEntry: PROC [entry: IntEntry];
-- atomically invalidates the value in the entry
-- an invalid entry always has entry.valid = -1

GetInt: PROC [entry: IntEntry] RETURNS [value: INT, valid: BOOL];
-- atomically retrieves the value in the entry

LookupRef: PROC
[type: Type, proc: ProcKey] RETURNS [entry: RefEntry];
-- looks up the entry corresponding to the type and proc
-- entry.valid => entry.ref is OK

FillRefEntry: PROC
[entry: RefEntry, value: REF] RETURNS [alreadyFull: BOOL];
-- fills the entry acquired by LookupRef
-- will not overwrite an already full entry

ClearRefEntry: PROC [entry: RefEntry];
-- atomically invalidates the value in the entry
-- an invalid entry always has entry.ref = NIL

GetRef: PROC [entry: RefEntry] RETURNS [value: REF, valid: BOOL];
-- atomically retrieves the value in the entry

GetStats: PROC
RETURNS [intProbes, intMisses, intFilled, refProbes, refMisses, refFilled: INT];

NewComponentMap: PROC [len: NAT] RETURNS [map: ComponentMap];
-- generates a new (empty) component map of the given size

FillNameComponent: PROC
[map: ComponentMap, index: INT, name: ROPE] RETURNS [alreadyFull: BOOL];
-- fills in a name component in the component map
-- will not overwrite an already full component
-- will ERROR InvalidIndex if index NOT IN [0..map.len)

FillTypeComponent: PROC
[map: ComponentMap, index: INT, type: Type] RETURNS [alreadyFull: BOOL];
-- fills in a type component in the component map
-- will not overwrite an already full component
-- will ERROR InvalidIndex if index NOT IN [0..map.len)

GetComponentAtIndex: PROC
[map: ComponentMap, index: INT] RETURNS [comp: ComponentEntry];
-- atomically returns the given component entry
-- will ERROR InvalidIndex if index NOT IN [0..map.len)

GetComponentForName: PROC
[map: ComponentMap, name: ROPE, case: BOOLTRUE]
RETURNS [index: INT, comp: ComponentEntry];
-- atomically returns the given component entry for the given name
-- IF case = TRUE, then name search is case-sensitive (Rope convention)
-- will return [-1, NullComponentEntry] if no such name

END.