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