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,11 +24,10 @@
  */
 
 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;
 
 /**

@@ -90,12 +89,12 @@
  * 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.
+ * 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,12 +414,10 @@
             }
         }
     }
 
     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();
 

@@ -432,10 +429,11 @@
         // 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,16 +490,16 @@
         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;
                 }
+                modCount++;
                 count--;
                 V oldValue = e.value;
                 e.value = null;
                 return oldValue;
             }

@@ -526,13 +524,13 @@
     /**
      * 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;
+        modCount++;
         count = 0;
     }
 
     /**
      * Creates a shallow copy of this hashtable. All the structure of the

@@ -717,18 +715,18 @@
 
             @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;
 
+                    e.value = null; // clear for gc.
+                    modCount++;
                     count--;
-                    e.value = null;
                     return true;
                 }
             }
             return false;
         }

@@ -937,18 +935,18 @@
         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;
                 }
+                e.value = null; // clear for gc
+                modCount++;
                 count--;
-                e.value = null;
                 return true;
             }
         }
         return false;
     }

@@ -1028,16 +1026,16 @@
         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;
                     }
+                    modCount++;
                     count--;
                 } else {
                     e.value = newValue;
                 }
                 return newValue;

@@ -1057,16 +1055,16 @@
         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;
                     }
+                    modCount++;
                     count--;
                 } else {
                     e.value = newValue;
                 }
                 return newValue;

@@ -1092,16 +1090,16 @@
         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;
                     }
+                    modCount++;
                     count--;
                 } else {
                     e.value = newValue;
                 }
                 return newValue;

@@ -1296,28 +1294,28 @@
      * 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;
+        final Entry<?,?>[] table = Hashtable.this.table;
         int index = table.length;
         Entry<?,?> entry;
         Entry<?,?> lastReturned;
-        int type;
+        final int type;
 
         /**
          * Indicates whether this Enumerator is serving as an Iterator
          * or an Enumeration.  (true -> Iterator).
          */
-        boolean 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 = modCount;
+        protected int expectedModCount = Hashtable.this.modCount;
 
         Enumerator(int type, boolean iterator) {
             this.type = type;
             this.iterator = iterator;
         }

@@ -1358,11 +1356,11 @@
         public boolean hasNext() {
             return hasMoreElements();
         }
 
         public T next() {
-            if (modCount != expectedModCount)
+            if (Hashtable.this.modCount != expectedModCount)
                 throw new ConcurrentModificationException();
             return nextElement();
         }
 
         public void remove() {

@@ -1379,18 +1377,18 @@
 
                 @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--;
+                        expectedModCount++;
                         lastReturned = null;
+                        Hashtable.this.modCount++;
+                        Hashtable.this.count--;
                         return;
                     }
                 }
                 throw new ConcurrentModificationException();
             }