src/share/classes/java/util/Hashtable.java

Print this page
rev 9756 : 8020860: cluster Hashtable/Vector field updates for better transactional memory behaviour
Reviewed-by: mduigou, martin, psandoz
Contributed-by: Sandhya.Viswanathan@intel.com, Mike.Duigou@oracle.com

*** 24,34 **** */ package java.util; import java.io.*; - import java.util.concurrent.ThreadLocalRandom; import java.util.function.BiConsumer; import java.util.function.Function; import java.util.function.BiFunction; /** --- 24,33 ----
*** 90,101 **** * after the iterator is created, in any way except through the iterator's own * <tt>remove</tt> method, the iterator will throw a {@link * ConcurrentModificationException}. Thus, in the face of concurrent * modification, the iterator fails quickly and cleanly, rather than risking * arbitrary, non-deterministic behavior at an undetermined time in the future. ! * The Enumerations returned by Hashtable's keys and elements methods are ! * <em>not</em> fail-fast. * * <p>Note that the fail-fast behavior of an iterator cannot be guaranteed * as it is, generally speaking, impossible to make any hard guarantees in the * presence of unsynchronized concurrent modification. Fail-fast iterators * throw <tt>ConcurrentModificationException</tt> on a best-effort basis. --- 89,100 ---- * after the iterator is created, in any way except through the iterator's own * <tt>remove</tt> method, the iterator will throw a {@link * ConcurrentModificationException}. Thus, in the face of concurrent * modification, the iterator fails quickly and cleanly, rather than risking * arbitrary, non-deterministic behavior at an undetermined time in the future. ! * The Enumerations returned by Hashtable's {@code #keys keys} and ! * {@code #elements elements} methods are <em>not</em> fail-fast. * * <p>Note that the fail-fast behavior of an iterator cannot be guaranteed * as it is, generally speaking, impossible to make any hard guarantees in the * presence of unsynchronized concurrent modification. Fail-fast iterators * throw <tt>ConcurrentModificationException</tt> on a best-effort basis.
*** 415,426 **** } } } private void addEntry(int hash, K key, V value, int index) { - modCount++; - Entry<?,?> tab[] = table; if (count >= threshold) { // Rehash the table if the threshold is exceeded rehash(); --- 414,423 ----
*** 432,441 **** --- 429,439 ---- // Creates the new entry. @SuppressWarnings("unchecked") Entry<K,V> e = (Entry<K,V>) tab[index]; tab[index] = new Entry<>(hash, key, value, e); count++; + modCount++; } /** * Maps the specified <code>key</code> to the specified * <code>value</code> in this hashtable. Neither the key nor the
*** 492,507 **** int index = (hash & 0x7FFFFFFF) % tab.length; @SuppressWarnings("unchecked") Entry<K,V> e = (Entry<K,V>)tab[index]; for(Entry<K,V> prev = null ; e != null ; prev = e, e = e.next) { if ((e.hash == hash) && e.key.equals(key)) { - modCount++; if (prev != null) { prev.next = e.next; } else { tab[index] = e.next; } count--; V oldValue = e.value; e.value = null; return oldValue; } --- 490,505 ---- int index = (hash & 0x7FFFFFFF) % tab.length; @SuppressWarnings("unchecked") Entry<K,V> e = (Entry<K,V>)tab[index]; for(Entry<K,V> prev = null ; e != null ; prev = e, e = e.next) { if ((e.hash == hash) && e.key.equals(key)) { if (prev != null) { prev.next = e.next; } else { tab[index] = e.next; } + modCount++; count--; V oldValue = e.value; e.value = null; return oldValue; }
*** 526,538 **** /** * Clears this hashtable so that it contains no keys. */ public synchronized void clear() { Entry<?,?> tab[] = table; - modCount++; for (int index = tab.length; --index >= 0; ) tab[index] = null; count = 0; } /** * Creates a shallow copy of this hashtable. All the structure of the --- 524,536 ---- /** * Clears this hashtable so that it contains no keys. */ public synchronized void clear() { Entry<?,?> tab[] = table; for (int index = tab.length; --index >= 0; ) tab[index] = null; + modCount++; count = 0; } /** * Creates a shallow copy of this hashtable. All the structure of the
*** 717,734 **** @SuppressWarnings("unchecked") Entry<K,V> e = (Entry<K,V>)tab[index]; for(Entry<K,V> prev = null; e != null; prev = e, e = e.next) { if (e.hash==hash && e.equals(entry)) { - modCount++; if (prev != null) prev.next = e.next; else tab[index] = e.next; count--; - e.value = null; return true; } } return false; } --- 715,732 ---- @SuppressWarnings("unchecked") Entry<K,V> e = (Entry<K,V>)tab[index]; for(Entry<K,V> prev = null; e != null; prev = e, e = e.next) { if (e.hash==hash && e.equals(entry)) { if (prev != null) prev.next = e.next; else tab[index] = e.next; + e.value = null; // clear for gc. + modCount++; count--; return true; } } return false; }
*** 937,954 **** int index = (hash & 0x7FFFFFFF) % tab.length; @SuppressWarnings("unchecked") Entry<K,V> e = (Entry<K,V>)tab[index]; for (Entry<K,V> prev = null; e != null; prev = e, e = e.next) { if ((e.hash == hash) && e.key.equals(key) && e.value.equals(value)) { - modCount++; if (prev != null) { prev.next = e.next; } else { tab[index] = e.next; } count--; - e.value = null; return true; } } return false; } --- 935,952 ---- int index = (hash & 0x7FFFFFFF) % tab.length; @SuppressWarnings("unchecked") Entry<K,V> e = (Entry<K,V>)tab[index]; for (Entry<K,V> prev = null; e != null; prev = e, e = e.next) { if ((e.hash == hash) && e.key.equals(key) && e.value.equals(value)) { if (prev != null) { prev.next = e.next; } else { tab[index] = e.next; } + e.value = null; // clear for gc + modCount++; count--; return true; } } return false; }
*** 1028,1043 **** Entry<K,V> e = (Entry<K,V>)tab[index]; for (Entry<K,V> prev = null; e != null; prev = e, e = e.next) { if (e.hash == hash && e.key.equals(key)) { V newValue = remappingFunction.apply(key, e.value); if (newValue == null) { - modCount++; if (prev != null) { prev.next = e.next; } else { tab[index] = e.next; } count--; } else { e.value = newValue; } return newValue; --- 1026,1041 ---- Entry<K,V> e = (Entry<K,V>)tab[index]; for (Entry<K,V> prev = null; e != null; prev = e, e = e.next) { if (e.hash == hash && e.key.equals(key)) { V newValue = remappingFunction.apply(key, e.value); if (newValue == null) { if (prev != null) { prev.next = e.next; } else { tab[index] = e.next; } + modCount++; count--; } else { e.value = newValue; } return newValue;
*** 1057,1072 **** Entry<K,V> e = (Entry<K,V>)tab[index]; for (Entry<K,V> prev = null; e != null; prev = e, e = e.next) { if (e.hash == hash && Objects.equals(e.key, key)) { V newValue = remappingFunction.apply(key, e.value); if (newValue == null) { - modCount++; if (prev != null) { prev.next = e.next; } else { tab[index] = e.next; } count--; } else { e.value = newValue; } return newValue; --- 1055,1070 ---- Entry<K,V> e = (Entry<K,V>)tab[index]; for (Entry<K,V> prev = null; e != null; prev = e, e = e.next) { if (e.hash == hash && Objects.equals(e.key, key)) { V newValue = remappingFunction.apply(key, e.value); if (newValue == null) { if (prev != null) { prev.next = e.next; } else { tab[index] = e.next; } + modCount++; count--; } else { e.value = newValue; } return newValue;
*** 1092,1107 **** Entry<K,V> e = (Entry<K,V>)tab[index]; for (Entry<K,V> prev = null; e != null; prev = e, e = e.next) { if (e.hash == hash && e.key.equals(key)) { V newValue = remappingFunction.apply(e.value, value); if (newValue == null) { - modCount++; if (prev != null) { prev.next = e.next; } else { tab[index] = e.next; } count--; } else { e.value = newValue; } return newValue; --- 1090,1105 ---- Entry<K,V> e = (Entry<K,V>)tab[index]; for (Entry<K,V> prev = null; e != null; prev = e, e = e.next) { if (e.hash == hash && e.key.equals(key)) { V newValue = remappingFunction.apply(e.value, value); if (newValue == null) { if (prev != null) { prev.next = e.next; } else { tab[index] = e.next; } + modCount++; count--; } else { e.value = newValue; } return newValue;
*** 1296,1323 **** * can be created with the Iterator methods disabled. This is necessary * to avoid unintentionally increasing the capabilities granted a user * by passing an Enumeration. */ private class Enumerator<T> implements Enumeration<T>, Iterator<T> { ! Entry<?,?>[] table = Hashtable.this.table; int index = table.length; Entry<?,?> entry; Entry<?,?> lastReturned; ! int type; /** * Indicates whether this Enumerator is serving as an Iterator * or an Enumeration. (true -> Iterator). */ ! boolean iterator; /** * The modCount value that the iterator believes that the backing * Hashtable should have. If this expectation is violated, the iterator * has detected concurrent modification. */ ! protected int expectedModCount = modCount; Enumerator(int type, boolean iterator) { this.type = type; this.iterator = iterator; } --- 1294,1321 ---- * can be created with the Iterator methods disabled. This is necessary * to avoid unintentionally increasing the capabilities granted a user * by passing an Enumeration. */ private class Enumerator<T> implements Enumeration<T>, Iterator<T> { ! final Entry<?,?>[] table = Hashtable.this.table; int index = table.length; Entry<?,?> entry; Entry<?,?> lastReturned; ! final int type; /** * Indicates whether this Enumerator is serving as an Iterator * or an Enumeration. (true -> Iterator). */ ! final boolean iterator; /** * The modCount value that the iterator believes that the backing * Hashtable should have. If this expectation is violated, the iterator * has detected concurrent modification. */ ! protected int expectedModCount = Hashtable.this.modCount; Enumerator(int type, boolean iterator) { this.type = type; this.iterator = iterator; }
*** 1358,1368 **** public boolean hasNext() { return hasMoreElements(); } public T next() { ! if (modCount != expectedModCount) throw new ConcurrentModificationException(); return nextElement(); } public void remove() { --- 1356,1366 ---- public boolean hasNext() { return hasMoreElements(); } public T next() { ! if (Hashtable.this.modCount != expectedModCount) throw new ConcurrentModificationException(); return nextElement(); } public void remove() {
*** 1379,1396 **** @SuppressWarnings("unchecked") Entry<K,V> e = (Entry<K,V>)tab[index]; for(Entry<K,V> prev = null; e != null; prev = e, e = e.next) { if (e == lastReturned) { - modCount++; - expectedModCount++; if (prev == null) tab[index] = e.next; else prev.next = e.next; ! count--; lastReturned = null; return; } } throw new ConcurrentModificationException(); } --- 1377,1394 ---- @SuppressWarnings("unchecked") Entry<K,V> e = (Entry<K,V>)tab[index]; for(Entry<K,V> prev = null; e != null; prev = e, e = e.next) { if (e == lastReturned) { if (prev == null) tab[index] = e.next; else prev.next = e.next; ! expectedModCount++; lastReturned = null; + Hashtable.this.modCount++; + Hashtable.this.count--; return; } } throw new ConcurrentModificationException(); }