1. package com.sun.corba.se.internal.orbutil;
  2. import org.omg.CORBA.INTERNAL;
  3. import org.omg.CORBA.CompletionStatus;
  4. public class CacheTable {
  5. class Entry {
  6. java.lang.Object key;
  7. int val;
  8. Entry next; // this chains the collision list of table "map"
  9. Entry rnext; // this chains the collision list of table "rmap"
  10. public Entry(java.lang.Object k, int v) {
  11. key = k;
  12. val = v;
  13. next = null;
  14. rnext = null;
  15. }
  16. }
  17. private boolean noReverseMap;
  18. // size must be power of 2
  19. static final int INITIAL_SIZE = 16;
  20. static final int MAX_SIZE = 1 << 30;
  21. int size;
  22. int entryCount;
  23. private Entry [] map;
  24. private Entry [] rmap;
  25. private CacheTable() {}
  26. public CacheTable(boolean u) {
  27. //System.out.println("using new cache table");
  28. noReverseMap = u;
  29. size = INITIAL_SIZE;
  30. entryCount = 0;
  31. initTables();
  32. }
  33. private void initTables() {
  34. map = new Entry[size];
  35. rmap = noReverseMap ? null : new Entry[size];
  36. }
  37. private void grow() {
  38. if (size == MAX_SIZE)
  39. return;
  40. Entry [] oldMap = map;
  41. int oldSize = size;
  42. size <<= 1;
  43. initTables();
  44. // now rehash the entries into the new table
  45. for (int i = 0; i < oldSize; i++) {
  46. for (Entry e = oldMap[i]; e != null; e = e.next)
  47. put_table(e.key, e.val);
  48. }
  49. }
  50. private int moduloTableSize(int h) {
  51. // these are the "supplemental hash function" copied from
  52. // java.util.HashMap, supposed to be "critical"
  53. h += ~(h << 9);
  54. h ^= (h >>> 14);
  55. h += (h << 4);
  56. h ^= (h >>> 10);
  57. return h & (size - 1);
  58. }
  59. private int hash(java.lang.Object key) {
  60. return moduloTableSize(System.identityHashCode(key));
  61. }
  62. private int hash(int val) {
  63. return moduloTableSize(val);
  64. }
  65. public final void put(java.lang.Object key, int val) {
  66. if (put_table(key, val)) {
  67. entryCount++;
  68. if (entryCount > size * 3 / 4)
  69. grow();
  70. }
  71. }
  72. private boolean put_table(java.lang.Object key, int val) {
  73. int index = hash(key);
  74. for (Entry e = map[index]; e != null; e = e.next) {
  75. if (e.key == key) {
  76. if (e.val != val) {
  77. throw new INTERNAL( MinorCodes.DUPLICATE_INDIRECTION_OFFSET,
  78. CompletionStatus.COMPLETED_NO );
  79. }
  80. // if we get here we are trying to put in the same key/val pair
  81. // this is a no-op, so we just return
  82. return false;
  83. }
  84. }
  85. // this means the key is not present in our table
  86. // then it shouldnt be present in our reverse table either
  87. Entry newEntry = new Entry(key, val);
  88. newEntry.next = map[index];
  89. map[index] = newEntry;
  90. if (!noReverseMap) {
  91. int rindex = hash(val);
  92. newEntry.rnext = rmap[rindex];
  93. rmap[rindex] = newEntry;
  94. }
  95. return true;
  96. }
  97. public final boolean containsKey(java.lang.Object key) {
  98. return (getVal(key) != -1);
  99. }
  100. public final int getVal(java.lang.Object key) {
  101. int index = hash(key);
  102. for (Entry e = map[index]; e != null; e = e.next) {
  103. if (e.key == key)
  104. return e.val;
  105. }
  106. return -1;
  107. }
  108. public final boolean containsVal(int val) {
  109. return (getKey(val) != null);
  110. }
  111. public final boolean containsOrderedVal(int val) {
  112. return containsVal(val);
  113. }
  114. public final java.lang.Object getKey(int val) {
  115. int index = hash(val);
  116. for (Entry e = rmap[index]; e != null; e = e.rnext) {
  117. if (e.val == val)
  118. return e.key;
  119. }
  120. return null;
  121. }
  122. public void done() {
  123. map = null;
  124. rmap = null;
  125. }
  126. }