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();
}