<> <> <> <> <> DIRECTORY IntHashTableThreaded; IntHashTableThreadedImpl: CEDAR MONITOR LOCKS table USING table: Table EXPORTS IntHashTableThreaded = { OPEN IntHashTableThreaded; <> Create: PUBLIC PROC [mod: SeqIndex _ 17, class: Class] RETURNS [Table] = { mod _ MAX[mod, minMod]; RETURN [NEW [TableRec _ [ class: class, size: 0, sizeLimit: mod, inhibitCount: 0, data: NEW [Seq[mod]] ]]]; }; minMod: SeqIndex = 2; GetSize: PUBLIC PROC [table: Table] RETURNS [INT] = { RETURN [table.size]; }; ComputeIndex: PROC [table: Table, key: Key] RETURNS [index: SeqIndex] = INLINE { key _ key MOD table.data.max; index _ IF key < 0 THEN key + table.data.max ELSE key; }; Match: PROC [table: Table, key: Key, node: Value] RETURNS [match: BOOL] = INLINE {match _ key = table.class.GetKey[node]}; Fetch: PUBLIC ENTRY PROC [table: Table, key: Key] RETURNS [found: BOOL, value: Value] = { OPEN table.class; ENABLE UNWIND => NULL; hash: SeqIndex _ ComputeIndex[table, key]; node: Value _ table.data[hash]; WHILE node # NIL DO IF Match[table, key, node] THEN RETURN [TRUE, node]; node _ GetLink[node]; ENDLOOP; RETURN [FALSE, NIL]; }; Replace: PUBLIC ENTRY PROC [table: Table, key: Key, value: Value] RETURNS [BOOL] = { OPEN table.class; ENABLE UNWIND => NULL; hash: SeqIndex _ ComputeIndex[table, key]; node: Value _ table.data[hash]; prev: Value _ NIL; WHILE node # NIL DO IF Match[table, key, node] THEN { SetLink[value, GetLink[node]]; IF prev = NIL THEN table.data[hash] _ value ELSE SetLink[prev, value]; RETURN [FALSE]}; prev _ node; node _ GetLink[node]; ENDLOOP; RETURN [FALSE]; }; Store: PUBLIC ENTRY PROC [table: Table, key: Key, value: Value] RETURNS [BOOL] = { OPEN table.class; ENABLE UNWIND => NULL; hash: SeqIndex _ ComputeIndex[table, key]; node: Value _ table.data[hash]; prev: Value _ NIL; WHILE node # NIL DO IF Match[table, key, node] THEN { SetLink[value, GetLink[node]]; IF prev = NIL THEN table.data[hash] _ value ELSE SetLink[prev, value]; RETURN [FALSE]}; prev _ node; node _ GetLink[node]; ENDLOOP; SetLink[value, table.data[hash]]; table.data[hash] _ value; IF (table.size _ table.size + 1) > table.sizeLimit AND table.inhibitCount = 0 THEN ReHash[table]; RETURN [TRUE]; }; Insert: PUBLIC ENTRY PROC [table: Table, key: Key, value: Value] RETURNS [BOOL] = { OPEN table.class; ENABLE UNWIND => NULL; hash: SeqIndex _ ComputeIndex[table, key]; node: Value _ table.data[hash]; WHILE node # NIL DO IF Match[table, key, node] THEN RETURN [FALSE]; node _ GetLink[node]; ENDLOOP; SetLink[value, table.data[hash]]; table.data[hash] _ value; IF (table.size _ table.size + 1) > table.sizeLimit AND table.inhibitCount = 0 THEN ReHash[table]; RETURN [TRUE]; }; Delete: PUBLIC ENTRY PROC [table: Table, key: Key] RETURNS [BOOL] = { OPEN table.class; ENABLE UNWIND => NULL; hash: SeqIndex _ ComputeIndex[table, key]; node: Value _ table.data[hash]; lag: Value _ NIL; WHILE node # NIL DO IF Match[table, key, node] THEN { IF lag = NIL THEN table.data[hash] _ GetLink[node] ELSE SetLink[lag, GetLink[node]]; table.size _ table.size - 1; RETURN [TRUE]; }; lag _ node; node _ GetLink[node]; ENDLOOP; RETURN [FALSE]; }; Pairs: PUBLIC PROC [table: Table, action: EachPairAction] RETURNS [quit: BOOL] = { OPEN table.class; node: Value _ NIL; {ENABLE UNWIND => index: CARDINAL _ table.data.max; DO [node, index] _ GetNext[table, node, index]; IF node = NIL THEN {quit _ FALSE; EXIT}; IF action[GetKey[node], node] THEN {quit _ TRUE; EXIT}; ENDLOOP; }; }; table.inhibitCount _ table.inhibitCount + WHILE table.inhibitCount = 0 AND table.size > table.sizeLimit DO ReHash[table] ENDLOOP; }; GetNext: ENTRY PROC [table: Table, node: Value, index: CARDINAL] RETURNS [Value, CARDINAL] = { OPEN table.class; ENABLE UNWIND => NULL; IF node # NIL THEN { node _ GetLink[node]; IF node # NIL THEN RETURN [node, index]; }; WHILE index > 0 DO index _ index - 1; node _ table.data[index]; IF node # NIL THEN RETURN [node, index]; ENDLOOP; RETURN [NIL, 0]; }; Erase: PUBLIC ENTRY PROC [table: Table] = { FOR i: CARDINAL IN [0..table.data.max) DO table.data[i] _ NIL ENDLOOP; table.size _ 0; }; ReHash: INTERNAL PROC [table: Table] = { OPEN table.class; oldData: REF Seq = table.data; newData: REF Seq; seek: CARDINAL = table.data.max * 2; newPTI, newMod: CARDINAL _ 0; IF primeTable[PrimeTableSize-1] > LAST[SeqIndex] THEN ERROR; FOR newPTI _ 0, newPTI+1 WHILE newPTI+1 < PrimeTableSize AND primeTable[newPTI] < seek DO NULL ENDLOOP; newMod _ primeTable[newPTI]; IF newMod = table.data.max THEN {table.sizeLimit _ LAST[INT]; RETURN}; table.sizeLimit _ newMod; table.data _ newData _ NEW [Seq[newMod]]; FOR i: NAT IN [0 .. oldData.max) DO next: Value _ NIL; FOR cur: Value _ oldData[i], next WHILE cur # NIL DO hash: SeqIndex _ ComputeIndex[table, GetKey[cur]]; next _ GetLink[cur]; SetLink[cur, newData[hash]]; newData[hash] _ cur; ENDLOOP; IF next # NIL THEN ERROR; ENDLOOP; table _ table; }; PrimeTableSize: NAT = 14; primeTable: ARRAY [0 .. PrimeTableSize) OF CARDINAL = [ 00002, 00005, 00011, 00023, 00053, 00113, 00251, 00509, 01019, 02039, 04079, 08179, 16369, 32749]; }.