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