<> <> <> <<>> DIRECTORY Basics USING [LowHalf], Checksum USING [ComputeChecksum], ImagerFontPrivate USING [FontID, FontIDRep], ImagerTransformation USING [Copy, Transformation, TransformationRep]; ImagerFontIDImpl: CEDAR MONITOR IMPORTS Basics, Checksum, ImagerTransformation EXPORTS ImagerFontPrivate ~ BEGIN FontID: TYPE ~ ImagerFontPrivate.FontID; FontIDRep: TYPE ~ ImagerFontPrivate.FontIDRep; Transformation: TYPE ~ ImagerTransformation.Transformation; TransformationRep: TYPE ~ ImagerTransformation.TransformationRep; hashTableSize: NAT ~ 253; HashIndex: TYPE ~ [0..hashTableSize); HashTable: TYPE ~ REF HashTableRep; HashTableRep: TYPE ~ ARRAY HashIndex OF FontIDList; FontIDList: TYPE ~ LIST OF FontID; hashTable: HashTable ~ NEW[HashTableRep _ ALL[NIL]]; entries: INT _ 0; collisions: INT _ 0; misses: INT _ 0; EqualT: PROC[p, q: Transformation] RETURNS[BOOL] ~ { RETURN[p.a=q.a AND p.b=q.b AND p.c=q.c AND p.d=q.d AND p.e=q.e AND p.f=q.f]; }; Hash: PROC[atom: ATOM, m: Transformation] RETURNS[CARDINAL] ~ TRUSTED INLINE { RETURN[Checksum.ComputeChecksum[cs: Basics.LowHalf[LOOPHOLE[atom]], nWords: SIZE[TransformationRep], p: LOOPHOLE[m]]]; }; GetID: PUBLIC ENTRY PROC [atom: ATOM, m: Transformation] RETURNS [FontID] ~ { ENABLE UNWIND => NULL; hash: CARDINAL ~ Hash[atom, m]; hashIndex: HashIndex ~ hash MOD hashTableSize; head: FontIDList ~ hashTable[hashIndex]; FOR each: FontIDList _ head, each.rest UNTIL each=NIL DO id: FontID ~ each.first; IF id.atom=atom AND EqualT[id.m, m] THEN RETURN[id] ELSE misses _ misses+1; ENDLOOP; { id: FontID ~ NEW[FontIDRep _ [atom: atom, m: ImagerTransformation.Copy[m]]]; hashTable[hashIndex] _ CONS[id, head]; entries _ entries+1; IF head#NIL THEN collisions _ collisions+1; RETURN[id]; }; }; END.