001 package ai;
002
003 /** The LookupTable represents an efficient hash table to Variations with
004 * two properties that make a regular HashMap unsuitable:
005 *
006 * - The LookupTable uses bounded memory, choosing to replace old
007 * cells rather than expand.
008 *
009 * - The LookupTable does not check for collisions in hashCode.
010 *
011 * As a result, LookupTable is fast, space-efficient, and
012 * occasionally wrong.
013 *
014 * LookupTable is thread-safe.
015 *
016 * @specfield mapping : Map<Object, Variation> //The map represented by this table
017 */
018 public class LookupTable {
019
020 // Each Variation can be fairly large (~40 bytes per cell)
021 // so one million table entries and 2G memory = 50 cells/table entry
022 // which is safe.
023
024 // Decreased it by a factor of 10 to be safe.
025 private final int SEEN_TABLE_SIZE = 100003;
026
027 //The variation we last saw at a given table entry.
028 private Variation[] seen;
029
030 //The whole key for a table entry
031 private int[] seenKeys;
032
033 // AF:
034 // mapping.get(x) = seen[x.hashCode() % SEEN_TABLE_SIZE]
035 // if seenKeys[x.hashCode() % SEEN_TABLE_SIZE] == x.hashCode()
036 // null otherwise
037
038 // RI:
039 // seenKeys[x]%SEEN_TABLE_SIZE = x for all x
040 // If the Variation associated with G is in seen[x], then
041 // seenKeys[x] = G.hashCode()
042
043 public LookupTable() {
044 seen = new Variation[SEEN_TABLE_SIZE];
045 seenKeys = new int[SEEN_TABLE_SIZE];
046 }
047
048 /**
049 * Get the value (probably) associated with an object, or null.
050 */
051 public Variation getTable(Object g) {
052 int key = g.hashCode();
053 int shortKey = (SEEN_TABLE_SIZE +
054 key%SEEN_TABLE_SIZE)%SEEN_TABLE_SIZE;
055 synchronized(seen) {
056 if (seenKeys[shortKey] == key)
057 return seen[shortKey];
058 }
059 return null;
060 }
061
062 /**
063 * Set the Variation associated with an object.
064 */
065 public void update(Object g, Variation var){
066 int key = g.hashCode();
067 int shortKey = (SEEN_TABLE_SIZE +
068 key%SEEN_TABLE_SIZE)%SEEN_TABLE_SIZE;
069 synchronized(seen) {
070 seen[shortKey] = var;
071 seenKeys[shortKey] = key;
072 }
073 }
074 }