summaryrefslogtreecommitdiffstats
path: root/luni/src/main/java
diff options
context:
space:
mode:
authorNarayan Kamath <narayan@google.com>2015-04-27 12:25:40 +0100
committerNarayan Kamath <narayan@google.com>2015-04-30 11:59:46 +0100
commitedf43d27e240d82106f39ae91404963c23987234 (patch)
tree8c690efa4627081d3d698a1ab7296824b9a12ded /luni/src/main/java
parent70be698e68966b8420ecb5873785351d7174f441 (diff)
downloadlibcore-edf43d27e240d82106f39ae91404963c23987234.zip
libcore-edf43d27e240d82106f39ae91404963c23987234.tar.gz
libcore-edf43d27e240d82106f39ae91404963c23987234.tar.bz2
Update JSR-166 to Revision 1.43
This is CVS HEAD as of Tue Mar 24 22:30:53 2015 UTC with android specific patches applied. All android patches have a clear "android-note" header. - Most changes are documentation related. - @hide tags have been applied to 1.8 APIs - Atomic*Updater have been updated to use VMStack.* APIs. bug: 20628776 bug: https://code.google.com/p/android/issues/detail?id=170073 (cherry picked from commit aa2ed9e105504f21641d919b410c692981cfe386) Change-Id: Ie7ce1780eda837f3455e6aa365861886956c4063
Diffstat (limited to 'luni/src/main/java')
-rw-r--r--luni/src/main/java/java/util/concurrent/AbstractExecutorService.java1
-rw-r--r--luni/src/main/java/java/util/concurrent/ArrayBlockingQueue.java161
-rw-r--r--luni/src/main/java/java/util/concurrent/BlockingDeque.java10
-rw-r--r--luni/src/main/java/java/util/concurrent/BlockingQueue.java1
-rw-r--r--luni/src/main/java/java/util/concurrent/ConcurrentHashMap.java425
-rw-r--r--luni/src/main/java/java/util/concurrent/ConcurrentLinkedQueue.java6
-rw-r--r--luni/src/main/java/java/util/concurrent/ConcurrentMap.java1
-rw-r--r--luni/src/main/java/java/util/concurrent/ConcurrentNavigableMap.java1
-rw-r--r--luni/src/main/java/java/util/concurrent/ConcurrentSkipListMap.java11
-rw-r--r--luni/src/main/java/java/util/concurrent/ConcurrentSkipListSet.java1
-rw-r--r--luni/src/main/java/java/util/concurrent/CopyOnWriteArraySet.java1
-rw-r--r--luni/src/main/java/java/util/concurrent/CountDownLatch.java1
-rw-r--r--luni/src/main/java/java/util/concurrent/CountedCompleter.java2
-rw-r--r--luni/src/main/java/java/util/concurrent/CyclicBarrier.java3
-rw-r--r--luni/src/main/java/java/util/concurrent/DelayQueue.java3
-rw-r--r--luni/src/main/java/java/util/concurrent/Exchanger.java3
-rw-r--r--luni/src/main/java/java/util/concurrent/Executor.java6
-rw-r--r--luni/src/main/java/java/util/concurrent/ExecutorCompletionService.java2
-rw-r--r--luni/src/main/java/java/util/concurrent/ExecutorService.java5
-rw-r--r--luni/src/main/java/java/util/concurrent/Executors.java1
-rw-r--r--luni/src/main/java/java/util/concurrent/ForkJoinPool.java13
-rw-r--r--luni/src/main/java/java/util/concurrent/ForkJoinTask.java18
-rw-r--r--luni/src/main/java/java/util/concurrent/FutureTask.java106
-rw-r--r--luni/src/main/java/java/util/concurrent/LinkedTransferQueue.java7
-rw-r--r--luni/src/main/java/java/util/concurrent/Phaser.java6
-rw-r--r--luni/src/main/java/java/util/concurrent/PriorityBlockingQueue.java2
-rw-r--r--luni/src/main/java/java/util/concurrent/RecursiveTask.java1
-rw-r--r--luni/src/main/java/java/util/concurrent/ScheduledExecutorService.java8
-rw-r--r--luni/src/main/java/java/util/concurrent/ScheduledThreadPoolExecutor.java122
-rw-r--r--luni/src/main/java/java/util/concurrent/Semaphore.java1
-rw-r--r--luni/src/main/java/java/util/concurrent/SynchronousQueue.java10
-rw-r--r--luni/src/main/java/java/util/concurrent/ThreadLocalRandom.java4
-rw-r--r--luni/src/main/java/java/util/concurrent/ThreadPoolExecutor.java5
-rw-r--r--luni/src/main/java/java/util/concurrent/TimeUnit.java73
-rw-r--r--luni/src/main/java/java/util/concurrent/atomic/AtomicBoolean.java1
-rw-r--r--luni/src/main/java/java/util/concurrent/atomic/AtomicInteger.java1
-rw-r--r--luni/src/main/java/java/util/concurrent/atomic/AtomicIntegerArray.java1
-rw-r--r--luni/src/main/java/java/util/concurrent/atomic/AtomicIntegerFieldUpdater.java5
-rw-r--r--luni/src/main/java/java/util/concurrent/atomic/AtomicLong.java1
-rw-r--r--luni/src/main/java/java/util/concurrent/atomic/AtomicLongArray.java1
-rw-r--r--luni/src/main/java/java/util/concurrent/atomic/AtomicLongFieldUpdater.java4
-rw-r--r--luni/src/main/java/java/util/concurrent/atomic/AtomicMarkableReference.java2
-rw-r--r--luni/src/main/java/java/util/concurrent/atomic/AtomicReference.java1
-rw-r--r--luni/src/main/java/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.java12
-rw-r--r--luni/src/main/java/java/util/concurrent/atomic/AtomicStampedReference.java2
-rw-r--r--luni/src/main/java/java/util/concurrent/locks/AbstractOwnableSynchronizer.java16
-rw-r--r--luni/src/main/java/java/util/concurrent/locks/AbstractQueuedLongSynchronizer.java25
-rw-r--r--luni/src/main/java/java/util/concurrent/locks/AbstractQueuedSynchronizer.java25
-rw-r--r--luni/src/main/java/java/util/concurrent/locks/Condition.java1
-rw-r--r--luni/src/main/java/java/util/concurrent/locks/Lock.java1
-rw-r--r--luni/src/main/java/java/util/concurrent/locks/LockSupport.java1
-rw-r--r--luni/src/main/java/java/util/concurrent/locks/ReentrantLock.java1
-rw-r--r--luni/src/main/java/java/util/concurrent/locks/ReentrantReadWriteLock.java9
-rw-r--r--luni/src/main/java/java/util/concurrent/package-info.java34
54 files changed, 708 insertions, 457 deletions
diff --git a/luni/src/main/java/java/util/concurrent/AbstractExecutorService.java b/luni/src/main/java/java/util/concurrent/AbstractExecutorService.java
index 23e68bb..26649a8 100644
--- a/luni/src/main/java/java/util/concurrent/AbstractExecutorService.java
+++ b/luni/src/main/java/java/util/concurrent/AbstractExecutorService.java
@@ -5,6 +5,7 @@
*/
package java.util.concurrent;
+
import java.util.*;
/**
diff --git a/luni/src/main/java/java/util/concurrent/ArrayBlockingQueue.java b/luni/src/main/java/java/util/concurrent/ArrayBlockingQueue.java
index 3cfe6d5..9dca1b3 100644
--- a/luni/src/main/java/java/util/concurrent/ArrayBlockingQueue.java
+++ b/luni/src/main/java/java/util/concurrent/ArrayBlockingQueue.java
@@ -5,13 +5,15 @@
*/
package java.util.concurrent;
-import java.util.concurrent.locks.Condition;
-import java.util.concurrent.locks.ReentrantLock;
+
+import java.lang.ref.WeakReference;
+import java.util.Arrays;
import java.util.AbstractQueue;
import java.util.Collection;
import java.util.Iterator;
import java.util.NoSuchElementException;
-import java.lang.ref.WeakReference;
+import java.util.concurrent.locks.Condition;
+import java.util.concurrent.locks.ReentrantLock;
// BEGIN android-note
// removed link to collections framework docs
@@ -46,7 +48,7 @@ import java.lang.ref.WeakReference;
*
* @since 1.5
* @author Doug Lea
- * @param <E> the type of elements held in this collection
+ * @param <E> the type of elements held in this queue
*/
public class ArrayBlockingQueue<E> extends AbstractQueue<E>
implements BlockingQueue<E>, java.io.Serializable {
@@ -95,14 +97,7 @@ public class ArrayBlockingQueue<E> extends AbstractQueue<E>
// Internal helper methods
/**
- * Circularly increment i.
- */
- final int inc(int i) {
- return (++i == items.length) ? 0 : i;
- }
-
- /**
- * Circularly decrement i.
+ * Circularly decrements array index i.
*/
final int dec(int i) {
return ((i == 0) ? items.length : i) - 1;
@@ -117,24 +112,15 @@ public class ArrayBlockingQueue<E> extends AbstractQueue<E>
}
/**
- * Throws NullPointerException if argument is null.
- *
- * @param v the element
- */
- private static void checkNotNull(Object v) {
- if (v == null)
- throw new NullPointerException();
- }
-
- /**
* Inserts element at current put position, advances, and signals.
* Call only when holding lock.
*/
private void enqueue(E x) {
// assert lock.getHoldCount() == 1;
// assert items[putIndex] == null;
+ final Object[] items = this.items;
items[putIndex] = x;
- putIndex = inc(putIndex);
+ if (++putIndex == items.length) putIndex = 0;
count++;
notEmpty.signal();
}
@@ -150,7 +136,7 @@ public class ArrayBlockingQueue<E> extends AbstractQueue<E>
@SuppressWarnings("unchecked")
E x = (E) items[takeIndex];
items[takeIndex] = null;
- takeIndex = inc(takeIndex);
+ if (++takeIndex == items.length) takeIndex = 0;
count--;
if (itrs != null)
itrs.elementDequeued();
@@ -171,7 +157,7 @@ public class ArrayBlockingQueue<E> extends AbstractQueue<E>
if (removeIndex == takeIndex) {
// removing front item; just advance
items[takeIndex] = null;
- takeIndex = inc(takeIndex);
+ if (++takeIndex == items.length) takeIndex = 0;
count--;
if (itrs != null)
itrs.elementDequeued();
@@ -179,17 +165,15 @@ public class ArrayBlockingQueue<E> extends AbstractQueue<E>
// an "interior" remove
// slide over all others up through putIndex.
- final int putIndex = this.putIndex;
- for (int i = removeIndex;;) {
- int next = inc(i);
- if (next != putIndex) {
- items[i] = items[next];
- i = next;
- } else {
- items[i] = null;
- this.putIndex = i;
+ for (int i = removeIndex, putIndex = this.putIndex;;) {
+ int pred = i;
+ if (++i == items.length) i = 0;
+ if (i == putIndex) {
+ items[pred] = null;
+ this.putIndex = pred;
break;
}
+ items[pred] = items[i];
}
count--;
if (itrs != null)
@@ -254,7 +238,7 @@ public class ArrayBlockingQueue<E> extends AbstractQueue<E>
int i = 0;
try {
for (E e : c) {
- checkNotNull(e);
+ if (e == null) throw new NullPointerException();
items[i++] = e;
}
} catch (ArrayIndexOutOfBoundsException ex) {
@@ -292,7 +276,7 @@ public class ArrayBlockingQueue<E> extends AbstractQueue<E>
* @throws NullPointerException if the specified element is null
*/
public boolean offer(E e) {
- checkNotNull(e);
+ if (e == null) throw new NullPointerException();
final ReentrantLock lock = this.lock;
lock.lock();
try {
@@ -315,7 +299,7 @@ public class ArrayBlockingQueue<E> extends AbstractQueue<E>
* @throws NullPointerException {@inheritDoc}
*/
public void put(E e) throws InterruptedException {
- checkNotNull(e);
+ if (e == null) throw new NullPointerException();
final ReentrantLock lock = this.lock;
lock.lockInterruptibly();
try {
@@ -338,7 +322,7 @@ public class ArrayBlockingQueue<E> extends AbstractQueue<E>
public boolean offer(E e, long timeout, TimeUnit unit)
throws InterruptedException {
- checkNotNull(e);
+ if (e == null) throw new NullPointerException();
long nanos = unit.toNanos(timeout);
final ReentrantLock lock = this.lock;
lock.lockInterruptibly();
@@ -462,11 +446,11 @@ public class ArrayBlockingQueue<E> extends AbstractQueue<E>
*/
public boolean remove(Object o) {
if (o == null) return false;
- final Object[] items = this.items;
final ReentrantLock lock = this.lock;
lock.lock();
try {
if (count > 0) {
+ final Object[] items = this.items;
final int putIndex = this.putIndex;
int i = takeIndex;
do {
@@ -474,7 +458,8 @@ public class ArrayBlockingQueue<E> extends AbstractQueue<E>
removeAt(i);
return true;
}
- } while ((i = inc(i)) != putIndex);
+ if (++i == items.length) i = 0;
+ } while (i != putIndex);
}
return false;
} finally {
@@ -492,17 +477,18 @@ public class ArrayBlockingQueue<E> extends AbstractQueue<E>
*/
public boolean contains(Object o) {
if (o == null) return false;
- final Object[] items = this.items;
final ReentrantLock lock = this.lock;
lock.lock();
try {
if (count > 0) {
+ final Object[] items = this.items;
final int putIndex = this.putIndex;
int i = takeIndex;
do {
if (o.equals(items[i]))
return true;
- } while ((i = inc(i)) != putIndex);
+ if (++i == items.length) i = 0;
+ } while (i != putIndex);
}
return false;
} finally {
@@ -524,19 +510,14 @@ public class ArrayBlockingQueue<E> extends AbstractQueue<E>
* @return an array containing all of the elements in this queue
*/
public Object[] toArray() {
- final Object[] items = this.items;
final ReentrantLock lock = this.lock;
lock.lock();
try {
- final int count = this.count;
- Object[] a = new Object[count];
- int n = items.length - takeIndex;
- if (count <= n) {
- System.arraycopy(items, takeIndex, a, 0, count);
- } else {
- System.arraycopy(items, takeIndex, a, 0, n);
- System.arraycopy(items, 0, a, n, count - n);
- }
+ final Object[] items = this.items;
+ final int end = takeIndex + count;
+ final Object[] a = Arrays.copyOfRange(items, takeIndex, end);
+ if (end != putIndex)
+ System.arraycopy(items, 0, a, items.length - takeIndex, putIndex);
return a;
} finally {
lock.unlock();
@@ -564,7 +545,7 @@ public class ArrayBlockingQueue<E> extends AbstractQueue<E>
* The following code can be used to dump the queue into a newly
* allocated array of {@code String}:
*
- * <pre> {@code String[] y = x.toArray(new String[0]);}</pre>
+ * <pre> {@code String[] y = x.toArray(new String[0]);}</pre>
*
* Note that {@code toArray(new Object[0])} is identical in function to
* {@code toArray()}.
@@ -580,24 +561,22 @@ public class ArrayBlockingQueue<E> extends AbstractQueue<E>
*/
@SuppressWarnings("unchecked")
public <T> T[] toArray(T[] a) {
- final Object[] items = this.items;
final ReentrantLock lock = this.lock;
lock.lock();
try {
+ final Object[] items = this.items;
final int count = this.count;
- final int len = a.length;
- if (len < count)
- a = (T[])java.lang.reflect.Array.newInstance(
- a.getClass().getComponentType(), count);
- int n = items.length - takeIndex;
- if (count <= n)
- System.arraycopy(items, takeIndex, a, 0, count);
- else {
- System.arraycopy(items, takeIndex, a, 0, n);
- System.arraycopy(items, 0, a, n, count - n);
+ final int firstLeg = Math.min(items.length - takeIndex, count);
+ if (a.length < count) {
+ a = (T[]) Arrays.copyOfRange(items, takeIndex, takeIndex + count,
+ a.getClass());
+ } else {
+ System.arraycopy(items, takeIndex, a, 0, firstLeg);
+ if (a.length > count)
+ a[count] = null;
}
- if (len > count)
- a[count] = null;
+ if (firstLeg < count)
+ System.arraycopy(items, 0, a, firstLeg, putIndex);
return a;
} finally {
lock.unlock();
@@ -612,14 +591,16 @@ public class ArrayBlockingQueue<E> extends AbstractQueue<E>
if (k == 0)
return "[]";
+ final Object[] items = this.items;
StringBuilder sb = new StringBuilder();
sb.append('[');
- for (int i = takeIndex; ; i = inc(i)) {
+ for (int i = takeIndex; ; ) {
Object e = items[i];
sb.append(e == this ? "(this Collection)" : e);
if (--k == 0)
return sb.append(']').toString();
sb.append(',').append(' ');
+ if (++i == items.length) i = 0;
}
} finally {
lock.unlock();
@@ -641,7 +622,8 @@ public class ArrayBlockingQueue<E> extends AbstractQueue<E>
int i = takeIndex;
do {
items[i] = null;
- } while ((i = inc(i)) != putIndex);
+ if (++i == items.length) i = 0;
+ } while (i != putIndex);
takeIndex = putIndex;
count = 0;
if (itrs != null)
@@ -671,7 +653,7 @@ public class ArrayBlockingQueue<E> extends AbstractQueue<E>
* @throws IllegalArgumentException {@inheritDoc}
*/
public int drainTo(Collection<? super E> c, int maxElements) {
- checkNotNull(c);
+ if (c == null) throw new NullPointerException();
if (c == this)
throw new IllegalArgumentException();
if (maxElements <= 0)
@@ -689,7 +671,7 @@ public class ArrayBlockingQueue<E> extends AbstractQueue<E>
E x = (E) items[take];
c.add(x);
items[take] = null;
- take = inc(take);
+ if (++take == items.length) take = 0;
i++;
}
return n;
@@ -717,12 +699,8 @@ public class ArrayBlockingQueue<E> extends AbstractQueue<E>
* Returns an iterator over the elements in this queue in proper sequence.
* The elements will be returned in order from first (head) to last (tail).
*
- * <p>The returned iterator is a "weakly consistent" iterator that
- * will never throw {@link java.util.ConcurrentModificationException
- * ConcurrentModificationException}, and guarantees to traverse
- * elements as they existed upon construction of the iterator, and
- * may (but is not guaranteed to) reflect any modifications
- * subsequent to construction.
+ * <p>The returned iterator is
+ * <a href="package-summary.html#Weakly"><i>weakly consistent</i></a>.
*
* @return an iterator over the elements in this queue in proper sequence
*/
@@ -796,13 +774,13 @@ public class ArrayBlockingQueue<E> extends AbstractQueue<E>
}
/** Incremented whenever takeIndex wraps around to 0 */
- int cycles = 0;
+ int cycles;
/** Linked list of weak iterator references */
private Node head;
/** Used to expunge stale iterators */
- private Node sweeper = null;
+ private Node sweeper;
private static final int SHORT_SWEEP_PROBES = 4;
private static final int LONG_SWEEP_PROBES = 16;
@@ -910,7 +888,7 @@ public class ArrayBlockingQueue<E> extends AbstractQueue<E>
}
/**
- * Called whenever an interior remove (not at takeIndex) occured.
+ * Called whenever an interior remove (not at takeIndex) occurred.
*
* Notifies all iterators, and expunges any that are now stale.
*/
@@ -1059,9 +1037,8 @@ public class ArrayBlockingQueue<E> extends AbstractQueue<E>
private int incCursor(int index) {
// assert lock.getHoldCount() == 1;
- index = inc(index);
- if (index == putIndex)
- index = NONE;
+ if (++index == items.length) index = 0;
+ if (index == putIndex) index = NONE;
return index;
}
@@ -1268,7 +1245,7 @@ public class ArrayBlockingQueue<E> extends AbstractQueue<E>
}
/**
- * Called whenever an interior remove (not at takeIndex) occured.
+ * Called whenever an interior remove (not at takeIndex) occurred.
*
* @return true if this iterator should be unlinked from itrs
*/
@@ -1277,17 +1254,18 @@ public class ArrayBlockingQueue<E> extends AbstractQueue<E>
if (isDetached())
return true;
- final int cycles = itrs.cycles;
final int takeIndex = ArrayBlockingQueue.this.takeIndex;
- final int prevCycles = this.prevCycles;
final int prevTakeIndex = this.prevTakeIndex;
final int len = items.length;
- int cycleDiff = cycles - prevCycles;
- if (removedIndex < takeIndex)
- cycleDiff++;
+ // distance from prevTakeIndex to removedIndex
final int removedDistance =
- (cycleDiff * len) + (removedIndex - prevTakeIndex);
- // assert removedDistance >= 0;
+ len * (itrs.cycles - this.prevCycles
+ + ((removedIndex < takeIndex) ? 1 : 0))
+ + (removedIndex - prevTakeIndex);
+ // assert itrs.cycles - this.prevCycles >= 0;
+ // assert itrs.cycles - this.prevCycles <= 1;
+ // assert removedDistance > 0;
+ // assert removedIndex != takeIndex;
int cursor = this.cursor;
if (cursor >= 0) {
int x = distance(cursor, prevTakeIndex, len);
@@ -1316,7 +1294,7 @@ public class ArrayBlockingQueue<E> extends AbstractQueue<E>
else if (x > removedDistance)
this.nextIndex = nextIndex = dec(nextIndex);
}
- else if (cursor < 0 && nextIndex < 0 && lastRet < 0) {
+ if (cursor < 0 && nextIndex < 0 && lastRet < 0) {
this.prevTakeIndex = DETACHED;
return true;
}
@@ -1354,4 +1332,5 @@ public class ArrayBlockingQueue<E> extends AbstractQueue<E>
// "remainingCapacity()=" + remainingCapacity());
// }
}
+
}
diff --git a/luni/src/main/java/java/util/concurrent/BlockingDeque.java b/luni/src/main/java/java/util/concurrent/BlockingDeque.java
index 8a393ba..b1437cc 100644
--- a/luni/src/main/java/java/util/concurrent/BlockingDeque.java
+++ b/luni/src/main/java/java/util/concurrent/BlockingDeque.java
@@ -5,6 +5,7 @@
*/
package java.util.concurrent;
+
import java.util.*;
/**
@@ -23,6 +24,7 @@ import java.util.*;
*
* <p>
* <table BORDER CELLPADDING=3 CELLSPACING=1>
+ * <caption>Summary of BlockingDeque methods</caption>
* <tr>
* <td ALIGN=CENTER COLSPAN = 5> <b>First Element (Head)</b></td>
* </tr>
@@ -98,6 +100,7 @@ import java.util.*;
*
* <p>
* <table BORDER CELLPADDING=3 CELLSPACING=1>
+ * <caption>Comparison of BlockingQueue and BlockingDeque methods</caption>
* <tr>
* <td ALIGN=CENTER> <b>{@code BlockingQueue} Method</b></td>
* <td ALIGN=CENTER> <b>Equivalent {@code BlockingDeque} Method</b></td>
@@ -606,9 +609,10 @@ public interface BlockingDeque<E> extends BlockingQueue<E>, Deque<E> {
// *** Stack methods ***
/**
- * Pushes an element onto the stack represented by this deque. In other
- * words, inserts the element at the front of this deque unless it would
- * violate capacity restrictions.
+ * Pushes an element onto the stack represented by this deque (in other
+ * words, at the head of this deque) if it is possible to do so
+ * immediately without violating capacity restrictions, throwing an
+ * {@code IllegalStateException} if no space is currently available.
*
* <p>This method is equivalent to {@link #addFirst(Object) addFirst}.
*
diff --git a/luni/src/main/java/java/util/concurrent/BlockingQueue.java b/luni/src/main/java/java/util/concurrent/BlockingQueue.java
index cc6d541..33d83b7 100644
--- a/luni/src/main/java/java/util/concurrent/BlockingQueue.java
+++ b/luni/src/main/java/java/util/concurrent/BlockingQueue.java
@@ -30,6 +30,7 @@ import java.util.Queue;
*
* <p>
* <table BORDER CELLPADDING=3 CELLSPACING=1>
+ * <caption>Summary of BlockingQueue methods</caption>
* <tr>
* <td></td>
* <td ALIGN=CENTER><em>Throws exception</em></td>
diff --git a/luni/src/main/java/java/util/concurrent/ConcurrentHashMap.java b/luni/src/main/java/java/util/concurrent/ConcurrentHashMap.java
index ea3b1e9..3ed54cf 100644
--- a/luni/src/main/java/java/util/concurrent/ConcurrentHashMap.java
+++ b/luni/src/main/java/java/util/concurrent/ConcurrentHashMap.java
@@ -10,9 +10,9 @@ import java.io.ObjectStreamField;
import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
+import java.util.AbstractMap;
import java.util.Arrays;
import java.util.Collection;
-import java.util.Comparator;
import java.util.ConcurrentModificationException;
import java.util.Enumeration;
import java.util.HashMap;
@@ -22,7 +22,6 @@ import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Set;
import java.util.concurrent.ConcurrentMap;
-import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.LockSupport;
import java.util.concurrent.locks.ReentrantLock;
@@ -99,7 +98,9 @@ import java.util.concurrent.locks.ReentrantLock;
* @param <K> the type of keys maintained by this map
* @param <V> the type of mapped values
*/
-public class ConcurrentHashMap<K,V> extends java.util.AbstractMap<K,V>
+// android-note: removed documentation about hidden newKeySet and newKeySet(int) APIs.
+// android-note: Added "extends AbstractMap<K, V>.
+public class ConcurrentHashMap<K,V> extends AbstractMap<K, V>
implements ConcurrentMap<K,V>, Serializable {
private static final long serialVersionUID = 7249069246763182397L;
@@ -208,14 +209,15 @@ public class ConcurrentHashMap<K,V> extends java.util.AbstractMap<K,V>
* The table is resized when occupancy exceeds a percentage
* threshold (nominally, 0.75, but see below). Any thread
* noticing an overfull bin may assist in resizing after the
- * initiating thread allocates and sets up the replacement
- * array. However, rather than stalling, these other threads may
- * proceed with insertions etc. The use of TreeBins shields us
- * from the worst case effects of overfilling while resizes are in
+ * initiating thread allocates and sets up the replacement array.
+ * However, rather than stalling, these other threads may proceed
+ * with insertions etc. The use of TreeBins shields us from the
+ * worst case effects of overfilling while resizes are in
* progress. Resizing proceeds by transferring bins, one by one,
- * from the table to the next table. To enable concurrency, the
- * next table must be (incrementally) prefilled with place-holders
- * serving as reverse forwarders to the old table. Because we are
+ * from the table to the next table. However, threads claim small
+ * blocks of indices to transfer (via field transferIndex) before
+ * doing so, reducing contention. A generation stamp in field
+ * sizeCtl ensures that resizings do not overlap. Because we are
* using power-of-two expansion, the elements from each bin must
* either stay at same index, or move with a power of two
* offset. We eliminate unnecessary node creation by catching
@@ -236,13 +238,19 @@ public class ConcurrentHashMap<K,V> extends java.util.AbstractMap<K,V>
* locks, average aggregate waits become shorter as resizing
* progresses. The transfer operation must also ensure that all
* accessible bins in both the old and new table are usable by any
- * traversal. This is arranged by proceeding from the last bin
- * (table.length - 1) up towards the first. Upon seeing a
- * forwarding node, traversals (see class Traverser) arrange to
- * move to the new table without revisiting nodes. However, to
- * ensure that no intervening nodes are skipped, bin splitting can
- * only begin after the associated reverse-forwarders are in
- * place.
+ * traversal. This is arranged in part by proceeding from the
+ * last bin (table.length - 1) up towards the first. Upon seeing
+ * a forwarding node, traversals (see class Traverser) arrange to
+ * move to the new table without revisiting nodes. To ensure that
+ * no intervening nodes are skipped even when moved out of order,
+ * a stack (see class TableStack) is created on first encounter of
+ * a forwarding node during a traversal, to maintain its place if
+ * later processing the current table. The need for these
+ * save/restore mechanics is relatively rare, but when one
+ * forwarding node is encountered, typically many more will be.
+ * So Traversers use a simple caching scheme to avoid creating so
+ * many new TableStack nodes. (Thanks to Peter Levart for
+ * suggesting use of a stack here.)
*
* The traversal scheme also applies to partial traversals of
* ranges of bins (via an alternate Traverser constructor)
@@ -274,16 +282,18 @@ public class ConcurrentHashMap<K,V> extends java.util.AbstractMap<K,V>
* related operations (which is the main reason we cannot use
* existing collections such as TreeMaps). TreeBins contain
* Comparable elements, but may contain others, as well as
- * elements that are Comparable but not necessarily Comparable
- * for the same T, so we cannot invoke compareTo among them. To
- * handle this, the tree is ordered primarily by hash value, then
- * by Comparable.compareTo order if applicable. On lookup at a
- * node, if elements are not comparable or compare as 0 then both
- * left and right children may need to be searched in the case of
- * tied hash values. (This corresponds to the full list search
- * that would be necessary if all elements were non-Comparable and
- * had tied hashes.) The red-black balancing code is updated from
- * pre-jdk-collections
+ * elements that are Comparable but not necessarily Comparable for
+ * the same T, so we cannot invoke compareTo among them. To handle
+ * this, the tree is ordered primarily by hash value, then by
+ * Comparable.compareTo order if applicable. On lookup at a node,
+ * if elements are not comparable or compare as 0 then both left
+ * and right children may need to be searched in the case of tied
+ * hash values. (This corresponds to the full list search that
+ * would be necessary if all elements were non-Comparable and had
+ * tied hashes.) On insertion, to keep a total ordering (or as
+ * close as is required here) across rebalancings, we compare
+ * classes and identityHashCodes as tie-breakers. The red-black
+ * balancing code is updated from pre-jdk-collections
* (http://gee.cs.oswego.edu/dl/classes/collections/RBCell.java)
* based in turn on Cormen, Leiserson, and Rivest "Introduction to
* Algorithms" (CLR).
@@ -313,6 +323,10 @@ public class ConcurrentHashMap<K,V> extends java.util.AbstractMap<K,V>
* unused "Segment" class that is instantiated in minimal form
* only when serializing.
*
+ * Also, solely for compatibility with previous versions of this
+ * class, it extends AbstractMap, even though all of its methods
+ * are overridden, so it is just useless baggage.
+ *
* This file is organized to make things a little easier to follow
* while reading than they might otherwise: First the main static
* declarations and utilities, then fields, then main public
@@ -321,6 +335,7 @@ public class ConcurrentHashMap<K,V> extends java.util.AbstractMap<K,V>
* bulk operations.
*/
+
/* ---------------- Constants -------------- */
/**
@@ -393,6 +408,23 @@ public class ConcurrentHashMap<K,V> extends java.util.AbstractMap<K,V>
*/
private static final int MIN_TRANSFER_STRIDE = 16;
+ /**
+ * The number of bits used for generation stamp in sizeCtl.
+ * Must be at least 6 for 32bit arrays.
+ */
+ private static int RESIZE_STAMP_BITS = 16;
+
+ /**
+ * The maximum number of threads that can help resize.
+ * Must fit in 32 - RESIZE_STAMP_BITS bits.
+ */
+ private static final int MAX_RESIZERS = (1 << (32 - RESIZE_STAMP_BITS)) - 1;
+
+ /**
+ * The bit shift for recording size stamp in sizeCtl.
+ */
+ private static final int RESIZE_STAMP_SHIFT = 32 - RESIZE_STAMP_BITS;
+
/*
* Encodings for Node hash fields. See above for explanation.
*/
@@ -504,7 +536,6 @@ public class ConcurrentHashMap<K,V> extends java.util.AbstractMap<K,V>
return (n < 0) ? 1 : (n >= MAXIMUM_CAPACITY) ? MAXIMUM_CAPACITY : n + 1;
}
-
/**
* Returns x's Class if it is of the form "class C implements
* Comparable<C>", else null.
@@ -605,11 +636,6 @@ public class ConcurrentHashMap<K,V> extends java.util.AbstractMap<K,V>
private transient volatile int transferIndex;
/**
- * The least available table index to split while resizing.
- */
- private transient volatile int transferOrigin;
-
- /**
* Spinlock (locked via CAS) used when resizing and/or creating CounterCells.
*/
private transient volatile int cellsBusy;
@@ -1035,8 +1061,8 @@ public class ConcurrentHashMap<K,V> extends java.util.AbstractMap<K,V>
* reflect any modifications subsequent to construction.
*
* @return the set view
- *
*/
+ // android-note : changed KeySetView<K,V> to Set<K> to maintain API compatibility.
public Set<K> keySet() {
KeySetView<K,V> ks;
return (ks = keySet) != null ? ks : (keySet = new KeySetView<K,V>(this, null));
@@ -1209,9 +1235,10 @@ public class ConcurrentHashMap<K,V> extends java.util.AbstractMap<K,V>
new Segment<?,?>[DEFAULT_CONCURRENCY_LEVEL];
for (int i = 0; i < segments.length; ++i)
segments[i] = new Segment<K,V>(LOAD_FACTOR);
- s.putFields().put("segments", segments);
- s.putFields().put("segmentShift", segmentShift);
- s.putFields().put("segmentMask", segmentMask);
+ java.io.ObjectOutputStream.PutField streamFields = s.putFields();
+ streamFields.put("segments", segments);
+ streamFields.put("segmentShift", segmentShift);
+ streamFields.put("segmentMask", segmentMask);
s.writeFields();
Node<K,V>[] t;
@@ -1264,8 +1291,8 @@ public class ConcurrentHashMap<K,V> extends java.util.AbstractMap<K,V>
int sz = (int)size;
n = tableSizeFor(sz + (sz >>> 1) + 1);
}
- @SuppressWarnings({"rawtypes","unchecked"})
- Node<K,V>[] tab = (Node<K,V>[])new Node[n];
+ @SuppressWarnings("unchecked")
+ Node<K,V>[] tab = (Node<K,V>[])new Node<?,?>[n];
int mask = n - 1;
long added = 0L;
while (p != null) {
@@ -1377,9 +1404,13 @@ public class ConcurrentHashMap<K,V> extends java.util.AbstractMap<K,V>
/**
* Legacy method testing if some key maps into the specified value
- * in this table. This method is identical in functionality to
+ * in this table.
+ *
+ * This method is identical in functionality to
* {@link #containsValue(Object)}, and exists solely to ensure
- * full compatibility with class {@link java.util.Hashtable}.
+ * full compatibility with class {@link java.util.Hashtable},
+ * which supported this method prior to introduction of the
+ * Java Collections framework.
*
* @param value a value to search for
* @return {@code true} if and only if some key maps to the
@@ -1388,6 +1419,7 @@ public class ConcurrentHashMap<K,V> extends java.util.AbstractMap<K,V>
* {@code false} otherwise
* @throws NullPointerException if the specified value is null
*/
+ // android-note : removed @deprecated tag from javadoc.
public boolean contains(Object value) {
// BEGIN android-note
// removed deprecation
@@ -1442,6 +1474,7 @@ public class ConcurrentHashMap<K,V> extends java.util.AbstractMap<K,V>
* Creates a new {@link Set} backed by a ConcurrentHashMap
* from the given type to {@code Boolean.TRUE}.
*
+ * @param <K> the element type of the returned set
* @return the new set
* @since 1.8
*
@@ -1458,9 +1491,10 @@ public class ConcurrentHashMap<K,V> extends java.util.AbstractMap<K,V>
*
* @param initialCapacity The implementation performs internal
* sizing to accommodate this many elements.
+ * @param <K> the element type of the returned set
+ * @return the new set
* @throws IllegalArgumentException if the initial capacity of
* elements is negative
- * @return the new set
* @since 1.8
*
* @hide
@@ -1483,7 +1517,7 @@ public class ConcurrentHashMap<K,V> extends java.util.AbstractMap<K,V>
*
* @hide
*/
- public Set<K> keySet(V mappedValue) {
+ public KeySetView<K,V> keySet(V mappedValue) {
if (mappedValue == null)
throw new NullPointerException();
return new KeySetView<K,V>(this, mappedValue);
@@ -1535,6 +1569,14 @@ public class ConcurrentHashMap<K,V> extends java.util.AbstractMap<K,V>
/* ---------------- Table Initialization and Resizing -------------- */
/**
+ * Returns the stamp bits for resizing a table of size n.
+ * Must be negative when shifted left by RESIZE_STAMP_SHIFT.
+ */
+ static final int resizeStamp(int n) {
+ return Integer.numberOfLeadingZeros(n) | (1 << (RESIZE_STAMP_BITS - 1));
+ }
+
+ /**
* Initializes table, using the size recorded in sizeCtl.
*/
private final Node<K,V>[] initTable() {
@@ -1546,8 +1588,8 @@ public class ConcurrentHashMap<K,V> extends java.util.AbstractMap<K,V>
try {
if ((tab = table) == null || tab.length == 0) {
int n = (sc > 0) ? sc : DEFAULT_CAPACITY;
- @SuppressWarnings({"rawtypes","unchecked"})
- Node<K,V>[] nt = (Node<K,V>[])new Node[n];
+ @SuppressWarnings("unchecked")
+ Node<K,V>[] nt = (Node<K,V>[])new Node<?,?>[n];
table = tab = nt;
sc = n - (n >>> 2);
}
@@ -1589,17 +1631,20 @@ public class ConcurrentHashMap<K,V> extends java.util.AbstractMap<K,V>
s = sumCount();
}
if (check >= 0) {
- Node<K,V>[] tab, nt; int sc;
+ Node<K,V>[] tab, nt; int n, sc;
while (s >= (long)(sc = sizeCtl) && (tab = table) != null &&
- tab.length < MAXIMUM_CAPACITY) {
+ (n = tab.length) < MAXIMUM_CAPACITY) {
+ int rs = resizeStamp(n);
if (sc < 0) {
- if (sc == -1 || transferIndex <= transferOrigin ||
- (nt = nextTable) == null)
+ if ((sc >>> RESIZE_STAMP_SHIFT) != rs || sc == rs + 1 ||
+ sc == rs + MAX_RESIZERS || (nt = nextTable) == null ||
+ transferIndex <= 0)
break;
- if (U.compareAndSwapInt(this, SIZECTL, sc, sc - 1))
+ if (U.compareAndSwapInt(this, SIZECTL, sc, sc + 1))
transfer(tab, nt);
}
- else if (U.compareAndSwapInt(this, SIZECTL, sc, -2))
+ else if (U.compareAndSwapInt(this, SIZECTL, sc,
+ (rs << RESIZE_STAMP_SHIFT) + 2))
transfer(tab, null);
s = sumCount();
}
@@ -1611,12 +1656,19 @@ public class ConcurrentHashMap<K,V> extends java.util.AbstractMap<K,V>
*/
final Node<K,V>[] helpTransfer(Node<K,V>[] tab, Node<K,V> f) {
Node<K,V>[] nextTab; int sc;
- if ((f instanceof ForwardingNode) &&
+ if (tab != null && (f instanceof ForwardingNode) &&
(nextTab = ((ForwardingNode<K,V>)f).nextTable) != null) {
- if (nextTab == nextTable && tab == table &&
- transferIndex > transferOrigin && (sc = sizeCtl) < -1 &&
- U.compareAndSwapInt(this, SIZECTL, sc, sc - 1))
- transfer(tab, nextTab);
+ int rs = resizeStamp(tab.length);
+ while (nextTab == nextTable && table == tab &&
+ (sc = sizeCtl) < 0) {
+ if ((sc >>> RESIZE_STAMP_SHIFT) != rs || sc == rs + 1 ||
+ sc == rs + MAX_RESIZERS || transferIndex <= 0)
+ break;
+ if (U.compareAndSwapInt(this, SIZECTL, sc, sc + 1)) {
+ transfer(tab, nextTab);
+ break;
+ }
+ }
return nextTab;
}
return table;
@@ -1638,8 +1690,8 @@ public class ConcurrentHashMap<K,V> extends java.util.AbstractMap<K,V>
if (U.compareAndSwapInt(this, SIZECTL, sc, -1)) {
try {
if (table == tab) {
- @SuppressWarnings({"rawtypes","unchecked"})
- Node<K,V>[] nt = (Node<K,V>[])new Node[n];
+ @SuppressWarnings("unchecked")
+ Node<K,V>[] nt = (Node<K,V>[])new Node<?,?>[n];
table = nt;
sc = n - (n >>> 2);
}
@@ -1650,9 +1702,21 @@ public class ConcurrentHashMap<K,V> extends java.util.AbstractMap<K,V>
}
else if (c <= sc || n >= MAXIMUM_CAPACITY)
break;
- else if (tab == table &&
- U.compareAndSwapInt(this, SIZECTL, sc, -2))
- transfer(tab, null);
+ else if (tab == table) {
+ int rs = resizeStamp(n);
+ if (sc < 0) {
+ Node<K,V>[] nt;
+ if ((sc >>> RESIZE_STAMP_SHIFT) != rs || sc == rs + 1 ||
+ sc == rs + MAX_RESIZERS || (nt = nextTable) == null ||
+ transferIndex <= 0)
+ break;
+ if (U.compareAndSwapInt(this, SIZECTL, sc, sc + 1))
+ transfer(tab, nt);
+ }
+ else if (U.compareAndSwapInt(this, SIZECTL, sc,
+ (rs << RESIZE_STAMP_SHIFT) + 2))
+ transfer(tab, null);
+ }
}
}
@@ -1666,35 +1730,27 @@ public class ConcurrentHashMap<K,V> extends java.util.AbstractMap<K,V>
stride = MIN_TRANSFER_STRIDE; // subdivide range
if (nextTab == null) { // initiating
try {
- @SuppressWarnings({"rawtypes","unchecked"})
- Node<K,V>[] nt = (Node<K,V>[])new Node[n << 1];
+ @SuppressWarnings("unchecked")
+ Node<K,V>[] nt = (Node<K,V>[])new Node<?,?>[n << 1];
nextTab = nt;
} catch (Throwable ex) { // try to cope with OOME
sizeCtl = Integer.MAX_VALUE;
return;
}
nextTable = nextTab;
- transferOrigin = n;
transferIndex = n;
- ForwardingNode<K,V> rev = new ForwardingNode<K,V>(tab);
- for (int k = n; k > 0;) { // progressively reveal ready slots
- int nextk = (k > stride) ? k - stride : 0;
- for (int m = nextk; m < k; ++m)
- nextTab[m] = rev;
- for (int m = n + nextk; m < n + k; ++m)
- nextTab[m] = rev;
- U.putOrderedInt(this, TRANSFERORIGIN, k = nextk);
- }
}
int nextn = nextTab.length;
ForwardingNode<K,V> fwd = new ForwardingNode<K,V>(nextTab);
boolean advance = true;
+ boolean finishing = false; // to ensure sweep before committing nextTab
for (int i = 0, bound = 0;;) {
- int nextIndex, nextBound, fh; Node<K,V> f;
+ Node<K,V> f; int fh;
while (advance) {
- if (--i >= bound)
+ int nextIndex, nextBound;
+ if (--i >= bound || finishing)
advance = false;
- else if ((nextIndex = transferIndex) <= transferOrigin) {
+ else if ((nextIndex = transferIndex) <= 0) {
i = -1;
advance = false;
}
@@ -1708,24 +1764,22 @@ public class ConcurrentHashMap<K,V> extends java.util.AbstractMap<K,V>
}
}
if (i < 0 || i >= n || i + n >= nextn) {
- for (int sc;;) {
- if (U.compareAndSwapInt(this, SIZECTL, sc = sizeCtl, ++sc)) {
- if (sc == -1) {
- nextTable = null;
- table = nextTab;
- sizeCtl = (n << 1) - (n >>> 1);
- }
- return;
- }
+ int sc;
+ if (finishing) {
+ nextTable = null;
+ table = nextTab;
+ sizeCtl = (n << 1) - (n >>> 1);
+ return;
}
- }
- else if ((f = tabAt(tab, i)) == null) {
- if (casTabAt(tab, i, null, fwd)) {
- setTabAt(nextTab, i, null);
- setTabAt(nextTab, i + n, null);
- advance = true;
+ if (U.compareAndSwapInt(this, SIZECTL, sc = sizeCtl, sc - 1)) {
+ if ((sc - 2) != resizeStamp(n) << RESIZE_STAMP_SHIFT)
+ return;
+ finishing = advance = true;
+ i = n; // recheck before commit
}
}
+ else if ((f = tabAt(tab, i)) == null)
+ advance = casTabAt(tab, i, null, fwd);
else if ((fh = f.hash) == MOVED)
advance = true; // already processed
else {
@@ -1757,6 +1811,10 @@ public class ConcurrentHashMap<K,V> extends java.util.AbstractMap<K,V>
else
hn = new Node<K,V>(ph, pk, pv, hn);
}
+ setTabAt(nextTab, i, ln);
+ setTabAt(nextTab, i + n, hn);
+ setTabAt(tab, i, fwd);
+ advance = true;
}
else if (f instanceof TreeBin) {
TreeBin<K,V> t = (TreeBin<K,V>)f;
@@ -1788,13 +1846,11 @@ public class ConcurrentHashMap<K,V> extends java.util.AbstractMap<K,V>
(hc != 0) ? new TreeBin<K,V>(lo) : t;
hn = (hc <= UNTREEIFY_THRESHOLD) ? untreeify(hi) :
(lc != 0) ? new TreeBin<K,V>(hi) : t;
+ setTabAt(nextTab, i, ln);
+ setTabAt(nextTab, i + n, hn);
+ setTabAt(tab, i, fwd);
+ advance = true;
}
- else
- ln = hn = null;
- setTabAt(nextTab, i, ln);
- setTabAt(nextTab, i + n, hn);
- setTabAt(tab, i, fwd);
- advance = true;
}
}
}
@@ -1810,12 +1866,9 @@ public class ConcurrentHashMap<K,V> extends java.util.AbstractMap<K,V>
private final void treeifyBin(Node<K,V>[] tab, int index) {
Node<K,V> b; int n, sc;
if (tab != null) {
- if ((n = tab.length) < MIN_TREEIFY_CAPACITY) {
- if (tab == table && (sc = sizeCtl) >= 0 &&
- U.compareAndSwapInt(this, SIZECTL, sc, -2))
- transfer(tab, null);
- }
- else if ((b = tabAt(tab, index)) != null) {
+ if ((n = tab.length) < MIN_TREEIFY_CAPACITY)
+ tryPresize(n << 1);
+ else if ((b = tabAt(tab, index)) != null && b.hash >= 0) {
synchronized (b) {
if (tabAt(tab, index) == b) {
TreeNode<K,V> hd = null, tl = null;
@@ -1881,7 +1934,7 @@ public class ConcurrentHashMap<K,V> extends java.util.AbstractMap<K,V>
final TreeNode<K,V> findTreeNode(int h, Object k, Class<?> kc) {
if (k != null) {
TreeNode<K,V> p = this;
- do {
+ do {
int ph, dir; K pk; TreeNode<K,V> q;
TreeNode<K,V> pl = p.left, pr = p.right;
if ((ph = p.hash) > h)
@@ -1890,25 +1943,25 @@ public class ConcurrentHashMap<K,V> extends java.util.AbstractMap<K,V>
p = pr;
else if ((pk = p.key) == k || (pk != null && k.equals(pk)))
return p;
- else if (pl == null && pr == null)
- break;
+ else if (pl == null)
+ p = pr;
+ else if (pr == null)
+ p = pl;
else if ((kc != null ||
(kc = comparableClassFor(k)) != null) &&
(dir = compareComparables(kc, k, pk)) != 0)
p = (dir < 0) ? pl : pr;
- else if (pl == null)
- p = pr;
- else if (pr == null ||
- (q = pr.findTreeNode(h, k, kc)) == null)
- p = pl;
- else
+ else if ((q = pr.findTreeNode(h, k, kc)) != null)
return q;
+ else
+ p = pl;
} while (p != null);
}
return null;
}
}
+
/* ---------------- TreeBins -------------- */
/**
@@ -1929,6 +1982,23 @@ public class ConcurrentHashMap<K,V> extends java.util.AbstractMap<K,V>
static final int READER = 4; // increment value for setting read lock
/**
+ * Tie-breaking utility for ordering insertions when equal
+ * hashCodes and non-comparable. We don't require a total
+ * order, just a consistent insertion rule to maintain
+ * equivalence across rebalancings. Tie-breaking further than
+ * necessary simplifies testing a bit.
+ */
+ static int tieBreakOrder(Object a, Object b) {
+ int d;
+ if (a == null || b == null ||
+ (d = a.getClass().getName().
+ compareTo(b.getClass().getName())) == 0)
+ d = (System.identityHashCode(a) <= System.identityHashCode(b) ?
+ -1 : 1);
+ return d;
+ }
+
+ /**
* Creates bin with initial set of nodes headed by b.
*/
TreeBin(TreeNode<K,V> b) {
@@ -1944,21 +2014,21 @@ public class ConcurrentHashMap<K,V> extends java.util.AbstractMap<K,V>
r = x;
}
else {
- Object key = x.key;
- int hash = x.hash;
+ K k = x.key;
+ int h = x.hash;
Class<?> kc = null;
for (TreeNode<K,V> p = r;;) {
int dir, ph;
- if ((ph = p.hash) > hash)
+ K pk = p.key;
+ if ((ph = p.hash) > h)
dir = -1;
- else if (ph < hash)
+ else if (ph < h)
dir = 1;
- else if ((kc != null ||
- (kc = comparableClassFor(key)) != null))
- dir = compareComparables(kc, key, p.key);
- else
- dir = 0;
- TreeNode<K,V> xp = p;
+ else if ((kc == null &&
+ (kc = comparableClassFor(k)) == null) ||
+ (dir = compareComparables(kc, k, pk)) == 0)
+ dir = tieBreakOrder(k, pk);
+ TreeNode<K,V> xp = p;
if ((p = (dir <= 0) ? p.left : p.right) == null) {
x.parent = xp;
if (dir <= 0)
@@ -1972,6 +2042,7 @@ public class ConcurrentHashMap<K,V> extends java.util.AbstractMap<K,V>
}
}
this.root = r;
+ assert checkInvariants(root);
}
/**
@@ -1995,7 +2066,7 @@ public class ConcurrentHashMap<K,V> extends java.util.AbstractMap<K,V>
private final void contendedLock() {
boolean waiting = false;
for (int s;;) {
- if (((s = lockState) & WRITER) == 0) {
+ if (((s = lockState) & ~WAITER) == 0) {
if (U.compareAndSwapInt(this, LOCKSTATE, s, WRITER)) {
if (waiting)
waiter = null;
@@ -2020,12 +2091,13 @@ public class ConcurrentHashMap<K,V> extends java.util.AbstractMap<K,V>
*/
final Node<K,V> find(int h, Object k) {
if (k != null) {
- for (Node<K,V> e = first; e != null; e = e.next) {
+ for (Node<K,V> e = first; e != null; ) {
int s; K ek;
if (((s = lockState) & (WAITER|WRITER)) != 0) {
if (e.hash == h &&
((ek = e.key) == k || (ek != null && k.equals(ek))))
return e;
+ e = e.next;
}
else if (U.compareAndSwapInt(this, LOCKSTATE, s,
s + READER)) {
@@ -2054,10 +2126,15 @@ public class ConcurrentHashMap<K,V> extends java.util.AbstractMap<K,V>
* Finds or adds a node.
* @return null if added
*/
+ /**
+ * Finds or adds a node.
+ * @return null if added
+ */
final TreeNode<K,V> putTreeVal(int h, K k, V v) {
Class<?> kc = null;
+ boolean searched = false;
for (TreeNode<K,V> p = root;;) {
- int dir, ph; K pk; TreeNode<K,V> q, pr;
+ int dir, ph; K pk;
if (p == null) {
first = root = new TreeNode<K,V>(h, k, v, null, null);
break;
@@ -2071,21 +2148,25 @@ public class ConcurrentHashMap<K,V> extends java.util.AbstractMap<K,V>
else if ((kc == null &&
(kc = comparableClassFor(k)) == null) ||
(dir = compareComparables(kc, k, pk)) == 0) {
- if (p.left == null)
- dir = 1;
- else if ((pr = p.right) == null ||
- (q = pr.findTreeNode(h, k, kc)) == null)
- dir = -1;
- else
- return q;
+ if (!searched) {
+ TreeNode<K,V> q, ch;
+ searched = true;
+ if (((ch = p.left) != null &&
+ (q = ch.findTreeNode(h, k, kc)) != null) ||
+ ((ch = p.right) != null &&
+ (q = ch.findTreeNode(h, k, kc)) != null))
+ return q;
+ }
+ dir = tieBreakOrder(k, pk);
}
+
TreeNode<K,V> xp = p;
- if ((p = (dir < 0) ? p.left : p.right) == null) {
+ if ((p = (dir <= 0) ? p.left : p.right) == null) {
TreeNode<K,V> x, f = first;
first = x = new TreeNode<K,V>(h, k, v, f, xp);
if (f != null)
f.prev = x;
- if (dir < 0)
+ if (dir <= 0)
xp.left = x;
else
xp.right = x;
@@ -2308,7 +2389,7 @@ public class ConcurrentHashMap<K,V> extends java.util.AbstractMap<K,V>
static <K,V> TreeNode<K,V> balanceDeletion(TreeNode<K,V> root,
TreeNode<K,V> x) {
- for (TreeNode<K,V> xp, xpl, xpr;;) {
+ for (TreeNode<K,V> xp, xpl, xpr;;) {
if (x == null || x == root)
return root;
else if ((xp = x.parent) == null) {
@@ -2440,8 +2521,20 @@ public class ConcurrentHashMap<K,V> extends java.util.AbstractMap<K,V>
/* ----------------Table Traversal -------------- */
/**
+ * Records the table, its length, and current traversal index for a
+ * traverser that must process a region of a forwarded table before
+ * proceeding with current table.
+ */
+ static final class TableStack<K,V> {
+ int length;
+ int index;
+ Node<K,V>[] tab;
+ TableStack<K,V> next;
+ }
+
+ /**
* Encapsulates traversal for methods such as containsValue; also
- * serves as a base class for other iterators.
+ * serves as a base class for other iterators and spliterators.
*
* Method advance visits once each still-valid node that was
* reachable upon iterator construction. It might miss some that
@@ -2463,6 +2556,7 @@ public class ConcurrentHashMap<K,V> extends java.util.AbstractMap<K,V>
static class Traverser<K,V> {
Node<K,V>[] tab; // current table; updated if resized
Node<K,V> next; // the next entry to use
+ TableStack<K,V> stack, spare; // to save/restore on ForwardingNodes
int index; // index of bin to use next
int baseIndex; // current index of initial table
int baseLimit; // index bound for initial table
@@ -2484,16 +2578,17 @@ public class ConcurrentHashMap<K,V> extends java.util.AbstractMap<K,V>
if ((e = next) != null)
e = e.next;
for (;;) {
- Node<K,V>[] t; int i, n; K ek; // must use locals in checks
+ Node<K,V>[] t; int i, n; // must use locals in checks
if (e != null)
return next = e;
if (baseIndex >= baseLimit || (t = tab) == null ||
(n = t.length) <= (i = index) || i < 0)
return next = null;
- if ((e = tabAt(t, index)) != null && e.hash < 0) {
+ if ((e = tabAt(t, i)) != null && e.hash < 0) {
if (e instanceof ForwardingNode) {
tab = ((ForwardingNode<K,V>)e).nextTable;
e = null;
+ pushState(t, i, n);
continue;
}
else if (e instanceof TreeBin)
@@ -2501,9 +2596,48 @@ public class ConcurrentHashMap<K,V> extends java.util.AbstractMap<K,V>
else
e = null;
}
- if ((index += baseSize) >= n)
- index = ++baseIndex; // visit upper slots if present
+ if (stack != null)
+ recoverState(n);
+ else if ((index = i + baseSize) >= n)
+ index = ++baseIndex; // visit upper slots if present
+ }
+ }
+
+ /**
+ * Saves traversal state upon encountering a forwarding node.
+ */
+ private void pushState(Node<K,V>[] t, int i, int n) {
+ TableStack<K,V> s = spare; // reuse if possible
+ if (s != null)
+ spare = s.next;
+ else
+ s = new TableStack<K,V>();
+ s.tab = t;
+ s.length = n;
+ s.index = i;
+ s.next = stack;
+ stack = s;
+ }
+
+ /**
+ * Possibly pops traversal state.
+ *
+ * @param n length of current table
+ */
+ private void recoverState(int n) {
+ TableStack<K,V> s; int len;
+ while ((s = stack) != null && (index += (len = s.length)) >= n) {
+ n = len;
+ index = s.index;
+ tab = s.tab;
+ s.tab = null;
+ TableStack<K,V> next = s.next;
+ s.next = spare; // save for reuse
+ stack = next;
+ spare = s;
}
+ if (s == null && (index += baseSize) >= n)
+ index = ++baseIndex;
}
}
@@ -2639,7 +2773,6 @@ public class ConcurrentHashMap<K,V> extends java.util.AbstractMap<K,V>
/**
* Base class for views.
- *
*/
abstract static class CollectionView<K,V,E>
implements Collection<E>, java.io.Serializable {
@@ -2797,13 +2930,12 @@ public class ConcurrentHashMap<K,V> extends java.util.AbstractMap<K,V>
* common value. This class cannot be directly instantiated.
* See {@link #keySet() keySet()},
* {@link #keySet(Object) keySet(V)},
- * {@link #newKeySet() newKeySet()},
- * {@link #newKeySet(int) newKeySet(int)}.
*
* @since 1.8
*
* @hide
*/
+ // android-note: removed references to hidden APIs.
public static class KeySetView<K,V> extends CollectionView<K,V,K>
implements Set<K>, java.io.Serializable {
private static final long serialVersionUID = 7249069246763182397L;
@@ -3162,7 +3294,6 @@ public class ConcurrentHashMap<K,V> extends java.util.AbstractMap<K,V>
private static final sun.misc.Unsafe U;
private static final long SIZECTL;
private static final long TRANSFERINDEX;
- private static final long TRANSFERORIGIN;
private static final long BASECOUNT;
private static final long CELLSBUSY;
private static final long CELLVALUE;
@@ -3177,8 +3308,6 @@ public class ConcurrentHashMap<K,V> extends java.util.AbstractMap<K,V>
(k.getDeclaredField("sizeCtl"));
TRANSFERINDEX = U.objectFieldOffset
(k.getDeclaredField("transferIndex"));
- TRANSFERORIGIN = U.objectFieldOffset
- (k.getDeclaredField("transferOrigin"));
BASECOUNT = U.objectFieldOffset
(k.getDeclaredField("baseCount"));
CELLSBUSY = U.objectFieldOffset
@@ -3195,6 +3324,10 @@ public class ConcurrentHashMap<K,V> extends java.util.AbstractMap<K,V>
} catch (Exception e) {
throw new Error(e);
}
+
+ // Reduce the risk of rare disastrous classloading in first call to
+ // LockSupport.park: https://bugs.openjdk.java.net/browse/JDK-8074773
+ Class<?> ensureLoaded = LockSupport.class;
}
}
diff --git a/luni/src/main/java/java/util/concurrent/ConcurrentLinkedQueue.java b/luni/src/main/java/java/util/concurrent/ConcurrentLinkedQueue.java
index b39a533..9010cbe 100644
--- a/luni/src/main/java/java/util/concurrent/ConcurrentLinkedQueue.java
+++ b/luni/src/main/java/java/util/concurrent/ConcurrentLinkedQueue.java
@@ -32,9 +32,9 @@ import java.util.Queue;
* does not permit the use of {@code null} elements.
*
* <p>This implementation employs an efficient <em>non-blocking</em>
- * algorithm based on one described in <a
- * href="http://www.cs.rochester.edu/u/michael/PODC96.html"> Simple,
- * Fast, and Practical Non-Blocking and Blocking Concurrent Queue
+ * algorithm based on one described in
+ * <a href="http://www.cs.rochester.edu/~scott/papers/1996_PODC_queues.pdf">
+ * Simple, Fast, and Practical Non-Blocking and Blocking Concurrent Queue
* Algorithms</a> by Maged M. Michael and Michael L. Scott.
*
* <p>Iterators are <i>weakly consistent</i>, returning elements
diff --git a/luni/src/main/java/java/util/concurrent/ConcurrentMap.java b/luni/src/main/java/java/util/concurrent/ConcurrentMap.java
index 27feeb2..1391f04 100644
--- a/luni/src/main/java/java/util/concurrent/ConcurrentMap.java
+++ b/luni/src/main/java/java/util/concurrent/ConcurrentMap.java
@@ -5,6 +5,7 @@
*/
package java.util.concurrent;
+
import java.util.Map;
// BEGIN android-note
diff --git a/luni/src/main/java/java/util/concurrent/ConcurrentNavigableMap.java b/luni/src/main/java/java/util/concurrent/ConcurrentNavigableMap.java
index e87fbee..17890ff 100644
--- a/luni/src/main/java/java/util/concurrent/ConcurrentNavigableMap.java
+++ b/luni/src/main/java/java/util/concurrent/ConcurrentNavigableMap.java
@@ -5,6 +5,7 @@
*/
package java.util.concurrent;
+
import java.util.*;
// BEGIN android-note
diff --git a/luni/src/main/java/java/util/concurrent/ConcurrentSkipListMap.java b/luni/src/main/java/java/util/concurrent/ConcurrentSkipListMap.java
index 4a76104..0e8b64a 100644
--- a/luni/src/main/java/java/util/concurrent/ConcurrentSkipListMap.java
+++ b/luni/src/main/java/java/util/concurrent/ConcurrentSkipListMap.java
@@ -5,6 +5,7 @@
*/
package java.util.concurrent;
+
import java.util.*;
// BEGIN android-note
@@ -215,7 +216,7 @@ public class ConcurrentSkipListMap<K,V> extends AbstractMap<K,V>
* highly contended cases.
*
* Unlike most skip-list implementations, index insertion and
- * deletion here require a separate traversal pass occuring after
+ * deletion here require a separate traversal pass occurring after
* the base-level action, to add or remove index nodes. This adds
* to single-threaded overhead, but improves contended
* multithreaded performance by narrowing interference windows,
@@ -2358,8 +2359,8 @@ public class ConcurrentSkipListMap<K,V> extends AbstractMap<K,V>
}
static final class Values<E> extends AbstractCollection<E> {
- private final ConcurrentNavigableMap<?, E> m;
- Values(ConcurrentNavigableMap<?, E> map) {
+ private final ConcurrentNavigableMap<?,E> m;
+ Values(ConcurrentNavigableMap<?,E> map) {
m = map;
}
public Iterator<E> iterator() {
@@ -2566,7 +2567,7 @@ public class ConcurrentSkipListMap<K,V> extends AbstractMap<K,V>
}
/**
- * Returns lowest absolute key (ignoring directonality).
+ * Returns lowest absolute key (ignoring directionality).
*/
private K lowestKey() {
ConcurrentSkipListMap.Node<K,V> n = loNode();
@@ -2577,7 +2578,7 @@ public class ConcurrentSkipListMap<K,V> extends AbstractMap<K,V>
}
/**
- * Returns highest absolute key (ignoring directonality).
+ * Returns highest absolute key (ignoring directionality).
*/
private K highestKey() {
ConcurrentSkipListMap.Node<K,V> n = hiNode();
diff --git a/luni/src/main/java/java/util/concurrent/ConcurrentSkipListSet.java b/luni/src/main/java/java/util/concurrent/ConcurrentSkipListSet.java
index f1402b6..13f1a43 100644
--- a/luni/src/main/java/java/util/concurrent/ConcurrentSkipListSet.java
+++ b/luni/src/main/java/java/util/concurrent/ConcurrentSkipListSet.java
@@ -5,6 +5,7 @@
*/
package java.util.concurrent;
+
import java.util.*;
// BEGIN android-note
diff --git a/luni/src/main/java/java/util/concurrent/CopyOnWriteArraySet.java b/luni/src/main/java/java/util/concurrent/CopyOnWriteArraySet.java
index 6fa8feb..347ed14 100644
--- a/luni/src/main/java/java/util/concurrent/CopyOnWriteArraySet.java
+++ b/luni/src/main/java/java/util/concurrent/CopyOnWriteArraySet.java
@@ -5,6 +5,7 @@
*/
package java.util.concurrent;
+
import java.util.*;
// BEGIN android-note
diff --git a/luni/src/main/java/java/util/concurrent/CountDownLatch.java b/luni/src/main/java/java/util/concurrent/CountDownLatch.java
index fe0fa65..77093f7 100644
--- a/luni/src/main/java/java/util/concurrent/CountDownLatch.java
+++ b/luni/src/main/java/java/util/concurrent/CountDownLatch.java
@@ -5,6 +5,7 @@
*/
package java.util.concurrent;
+
import java.util.concurrent.locks.AbstractQueuedSynchronizer;
/**
diff --git a/luni/src/main/java/java/util/concurrent/CountedCompleter.java b/luni/src/main/java/java/util/concurrent/CountedCompleter.java
index d5f794e..b868037 100644
--- a/luni/src/main/java/java/util/concurrent/CountedCompleter.java
+++ b/luni/src/main/java/java/util/concurrent/CountedCompleter.java
@@ -686,7 +686,7 @@ public abstract class CountedCompleter<T> extends ForkJoinTask<T> {
}
/**
- * Returns the result of the computation. By default
+ * Returns the result of the computation. By default,
* returns {@code null}, which is appropriate for {@code Void}
* actions, but in other cases should be overridden, almost
* always to return a field or function of a field that
diff --git a/luni/src/main/java/java/util/concurrent/CyclicBarrier.java b/luni/src/main/java/java/util/concurrent/CyclicBarrier.java
index e1a7bee..d698501 100644
--- a/luni/src/main/java/java/util/concurrent/CyclicBarrier.java
+++ b/luni/src/main/java/java/util/concurrent/CyclicBarrier.java
@@ -5,6 +5,7 @@
*/
package java.util.concurrent;
+
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
@@ -125,7 +126,7 @@ public class CyclicBarrier {
private final Condition trip = lock.newCondition();
/** The number of parties */
private final int parties;
- /* The command to run when tripped */
+ /** The command to run when tripped */
private final Runnable barrierCommand;
/** The current generation */
private Generation generation = new Generation();
diff --git a/luni/src/main/java/java/util/concurrent/DelayQueue.java b/luni/src/main/java/java/util/concurrent/DelayQueue.java
index 945249e..e4a715e 100644
--- a/luni/src/main/java/java/util/concurrent/DelayQueue.java
+++ b/luni/src/main/java/java/util/concurrent/DelayQueue.java
@@ -5,6 +5,7 @@
*/
package java.util.concurrent;
+
import static java.util.concurrent.TimeUnit.NANOSECONDS;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
@@ -60,7 +61,7 @@ public class DelayQueue<E extends Delayed> extends AbstractQueue<E>
* signalled. So waiting threads must be prepared to acquire
* and lose leadership while waiting.
*/
- private Thread leader = null;
+ private Thread leader;
/**
* Condition signalled when a newer element becomes available
diff --git a/luni/src/main/java/java/util/concurrent/Exchanger.java b/luni/src/main/java/java/util/concurrent/Exchanger.java
index 01d5960..60871b4 100644
--- a/luni/src/main/java/java/util/concurrent/Exchanger.java
+++ b/luni/src/main/java/java/util/concurrent/Exchanger.java
@@ -6,9 +6,6 @@
*/
package java.util.concurrent;
-import java.util.concurrent.atomic.AtomicInteger;
-import java.util.concurrent.atomic.AtomicReference;
-import java.util.concurrent.locks.LockSupport;
/**
* A synchronization point at which threads can pair and swap elements
diff --git a/luni/src/main/java/java/util/concurrent/Executor.java b/luni/src/main/java/java/util/concurrent/Executor.java
index f55209a..095ebfc 100644
--- a/luni/src/main/java/java/util/concurrent/Executor.java
+++ b/luni/src/main/java/java/util/concurrent/Executor.java
@@ -12,7 +12,7 @@ package java.util.concurrent;
* mechanics of how each task will be run, including details of thread
* use, scheduling, etc. An {@code Executor} is normally used
* instead of explicitly creating threads. For example, rather than
- * invoking {@code new Thread(new(RunnableTask())).start()} for each
+ * invoking {@code new Thread(new RunnableTask()).start()} for each
* of a set of tasks, you might use:
*
* <pre>
@@ -52,7 +52,7 @@ package java.util.concurrent;
*
* <pre> {@code
* class SerialExecutor implements Executor {
- * final Queue<Runnable> tasks = new ArrayDeque<Runnable>();
+ * final Queue<Runnable> tasks = new ArrayDeque<>();
* final Executor executor;
* Runnable active;
*
@@ -61,7 +61,7 @@ package java.util.concurrent;
* }
*
* public synchronized void execute(final Runnable r) {
- * tasks.offer(new Runnable() {
+ * tasks.add(new Runnable() {
* public void run() {
* try {
* r.run();
diff --git a/luni/src/main/java/java/util/concurrent/ExecutorCompletionService.java b/luni/src/main/java/java/util/concurrent/ExecutorCompletionService.java
index c0d6006..9514246 100644
--- a/luni/src/main/java/java/util/concurrent/ExecutorCompletionService.java
+++ b/luni/src/main/java/java/util/concurrent/ExecutorCompletionService.java
@@ -132,7 +132,7 @@ public class ExecutorCompletionService<V> implements CompletionService<V> {
* @param completionQueue the queue to use as the completion queue
* normally one dedicated for use by this service. This
* queue is treated as unbounded -- failed attempted
- * {@code Queue.add} operations for completed taskes cause
+ * {@code Queue.add} operations for completed tasks cause
* them not to be retrievable.
* @throws NullPointerException if executor or completionQueue are {@code null}
*/
diff --git a/luni/src/main/java/java/util/concurrent/ExecutorService.java b/luni/src/main/java/java/util/concurrent/ExecutorService.java
index 4599f59..2173529 100644
--- a/luni/src/main/java/java/util/concurrent/ExecutorService.java
+++ b/luni/src/main/java/java/util/concurrent/ExecutorService.java
@@ -5,6 +5,7 @@
*/
package java.util.concurrent;
+
import java.util.List;
import java.util.Collection;
@@ -29,8 +30,8 @@ import java.util.Collection;
* reclamation of its resources.
*
* <p>Method {@code submit} extends base method {@link
- * Executor#execute} by creating and returning a {@link Future} that
- * can be used to cancel execution and/or wait for completion.
+ * Executor#execute(Runnable)} by creating and returning a {@link Future}
+ * that can be used to cancel execution and/or wait for completion.
* Methods {@code invokeAny} and {@code invokeAll} perform the most
* commonly useful forms of bulk execution, executing a collection of
* tasks and then waiting for at least one, or all, to
diff --git a/luni/src/main/java/java/util/concurrent/Executors.java b/luni/src/main/java/java/util/concurrent/Executors.java
index 53c68fc..8731372 100644
--- a/luni/src/main/java/java/util/concurrent/Executors.java
+++ b/luni/src/main/java/java/util/concurrent/Executors.java
@@ -5,6 +5,7 @@
*/
package java.util.concurrent;
+
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.security.AccessControlContext;
diff --git a/luni/src/main/java/java/util/concurrent/ForkJoinPool.java b/luni/src/main/java/java/util/concurrent/ForkJoinPool.java
index 9448616..5bcac28 100644
--- a/luni/src/main/java/java/util/concurrent/ForkJoinPool.java
+++ b/luni/src/main/java/java/util/concurrent/ForkJoinPool.java
@@ -12,14 +12,6 @@ import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
-import java.util.concurrent.AbstractExecutorService;
-import java.util.concurrent.Callable;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Future;
-import java.util.concurrent.RejectedExecutionException;
-import java.util.concurrent.RunnableFuture;
-import java.util.concurrent.ThreadLocalRandom;
-import java.util.concurrent.TimeUnit;
/**
* An {@link ExecutorService} for running {@link ForkJoinTask}s.
@@ -498,6 +490,7 @@ public class ForkJoinPool extends AbstractExecutorService {
* (7) Exported methods
* (8) Static block initializing statics in minimally dependent order
*/
+ // android-note: Removed references to CountedCompleters.
// Static utilities
@@ -524,8 +517,8 @@ public class ForkJoinPool extends AbstractExecutorService {
* Returns a new worker thread operating in the given pool.
*
* @param pool the pool this thread works in
- * @throws NullPointerException if the pool is null
* @return the new worker thread
+ * @throws NullPointerException if the pool is null
*/
public ForkJoinWorkerThread newThread(ForkJoinPool pool);
}
@@ -2090,7 +2083,7 @@ public class ForkJoinPool extends AbstractExecutorService {
w.currentSteal = ps;
}
}
- else if (active) { // decrement active count without queuing
+ else if (active) { // decrement active count without queuing
long nc = ((c = ctl) & ~AC_MASK) | ((c & AC_MASK) - AC_UNIT);
if ((int)(nc >> AC_SHIFT) + parallelism == 0)
break; // bypass decrement-then-increment
diff --git a/luni/src/main/java/java/util/concurrent/ForkJoinTask.java b/luni/src/main/java/java/util/concurrent/ForkJoinTask.java
index c6bc6de..d34cae3 100644
--- a/luni/src/main/java/java/util/concurrent/ForkJoinTask.java
+++ b/luni/src/main/java/java/util/concurrent/ForkJoinTask.java
@@ -12,14 +12,6 @@ import java.util.List;
import java.util.RandomAccess;
import java.lang.ref.WeakReference;
import java.lang.ref.ReferenceQueue;
-import java.util.concurrent.Callable;
-import java.util.concurrent.CancellationException;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.Future;
-import java.util.concurrent.RejectedExecutionException;
-import java.util.concurrent.RunnableFuture;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.TimeoutException;
import java.util.concurrent.locks.ReentrantLock;
import java.lang.reflect.Constructor;
@@ -177,6 +169,8 @@ import java.lang.reflect.Constructor;
* @since 1.7
* @author Doug Lea
*/
+// android-note: Removed references to hidden apis commonPool, CountedCompleter
+// etc.
public abstract class ForkJoinTask<V> implements Future<V>, Serializable {
/*
@@ -407,11 +401,13 @@ public abstract class ForkJoinTask<V> implements Future<V>, Serializable {
final Throwable ex;
ExceptionNode next;
final long thrower; // use id not ref to avoid weak cycles
+ final int hashCode; // store task hashCode before weak ref disappears
ExceptionNode(ForkJoinTask<?> task, Throwable ex, ExceptionNode next) {
super(task, exceptionTableRefQueue);
this.ex = ex;
this.next = next;
this.thrower = Thread.currentThread().getId();
+ this.hashCode = System.identityHashCode(task);
}
}
@@ -573,9 +569,9 @@ public abstract class ForkJoinTask<V> implements Future<V>, Serializable {
private static void expungeStaleExceptions() {
for (Object x; (x = exceptionTableRefQueue.poll()) != null;) {
if (x instanceof ExceptionNode) {
- ForkJoinTask<?> key = ((ExceptionNode)x).get();
+ int hashCode = ((ExceptionNode)x).hashCode;
ExceptionNode[] t = exceptionTable;
- int i = System.identityHashCode(key) & (t.length - 1);
+ int i = hashCode & (t.length - 1);
ExceptionNode e = t[i];
ExceptionNode pred = null;
while (e != null) {
@@ -1413,8 +1409,6 @@ public abstract class ForkJoinTask<V> implements Future<V>, Serializable {
try {
result = callable.call();
return true;
- } catch (Error err) {
- throw err;
} catch (RuntimeException rex) {
throw rex;
} catch (Exception ex) {
diff --git a/luni/src/main/java/java/util/concurrent/FutureTask.java b/luni/src/main/java/java/util/concurrent/FutureTask.java
index 114fe49..5e24fc8 100644
--- a/luni/src/main/java/java/util/concurrent/FutureTask.java
+++ b/luni/src/main/java/java/util/concurrent/FutureTask.java
@@ -5,6 +5,7 @@
*/
package java.util.concurrent;
+
import java.util.concurrent.locks.LockSupport;
/**
@@ -134,7 +135,7 @@ public class FutureTask<V> implements RunnableFuture<V> {
public boolean cancel(boolean mayInterruptIfRunning) {
if (!(state == NEW &&
- UNSAFE.compareAndSwapInt(this, stateOffset, NEW,
+ U.compareAndSwapInt(this, STATE, NEW,
mayInterruptIfRunning ? INTERRUPTING : CANCELLED)))
return false;
try { // in case call to interrupt throws exception
@@ -144,7 +145,7 @@ public class FutureTask<V> implements RunnableFuture<V> {
if (t != null)
t.interrupt();
} finally { // final state
- UNSAFE.putOrderedInt(this, stateOffset, INTERRUPTED);
+ U.putOrderedInt(this, STATE, INTERRUPTED);
}
}
} finally {
@@ -198,9 +199,9 @@ public class FutureTask<V> implements RunnableFuture<V> {
* @param v the value
*/
protected void set(V v) {
- if (UNSAFE.compareAndSwapInt(this, stateOffset, NEW, COMPLETING)) {
+ if (U.compareAndSwapInt(this, STATE, NEW, COMPLETING)) {
outcome = v;
- UNSAFE.putOrderedInt(this, stateOffset, NORMAL); // final state
+ U.putOrderedInt(this, STATE, NORMAL); // final state
finishCompletion();
}
}
@@ -216,17 +217,16 @@ public class FutureTask<V> implements RunnableFuture<V> {
* @param t the cause of failure
*/
protected void setException(Throwable t) {
- if (UNSAFE.compareAndSwapInt(this, stateOffset, NEW, COMPLETING)) {
+ if (U.compareAndSwapInt(this, STATE, NEW, COMPLETING)) {
outcome = t;
- UNSAFE.putOrderedInt(this, stateOffset, EXCEPTIONAL); // final state
+ U.putOrderedInt(this, STATE, EXCEPTIONAL); // final state
finishCompletion();
}
}
public void run() {
if (state != NEW ||
- !UNSAFE.compareAndSwapObject(this, runnerOffset,
- null, Thread.currentThread()))
+ !U.compareAndSwapObject(this, RUNNER, null, Thread.currentThread()))
return;
try {
Callable<V> c = callable;
@@ -263,12 +263,11 @@ public class FutureTask<V> implements RunnableFuture<V> {
* designed for use with tasks that intrinsically execute more
* than once.
*
- * @return true if successfully run and reset
+ * @return {@code true} if successfully run and reset
*/
protected boolean runAndReset() {
if (state != NEW ||
- !UNSAFE.compareAndSwapObject(this, runnerOffset,
- null, Thread.currentThread()))
+ !U.compareAndSwapObject(this, RUNNER, null, Thread.currentThread()))
return false;
boolean ran = false;
int s = state;
@@ -335,7 +334,7 @@ public class FutureTask<V> implements RunnableFuture<V> {
private void finishCompletion() {
// assert state > COMPLETING;
for (WaitNode q; (q = waiters) != null;) {
- if (UNSAFE.compareAndSwapObject(this, waitersOffset, q, null)) {
+ if (U.compareAndSwapObject(this, WAITERS, q, null)) {
for (;;) {
Thread t = q.thread;
if (t != null) {
@@ -362,39 +361,61 @@ public class FutureTask<V> implements RunnableFuture<V> {
*
* @param timed true if use timed waits
* @param nanos time to wait, if timed
- * @return state upon completion
+ * @return state upon completion or at timeout
*/
private int awaitDone(boolean timed, long nanos)
throws InterruptedException {
- final long deadline = timed ? System.nanoTime() + nanos : 0L;
+ // The code below is very delicate, to achieve these goals:
+ // - call nanoTime exactly once for each call to park
+ // - if nanos <= 0, return promptly without allocation or nanoTime
+ // - if nanos == Long.MIN_VALUE, don't underflow
+ // - if nanos == Long.MAX_VALUE, and nanoTime is non-monotonic
+ // and we suffer a spurious wakeup, we will do no worse than
+ // to park-spin for a while
+ long startTime = 0L; // Special value 0L means not yet parked
WaitNode q = null;
boolean queued = false;
for (;;) {
- if (Thread.interrupted()) {
- removeWaiter(q);
- throw new InterruptedException();
- }
-
int s = state;
if (s > COMPLETING) {
if (q != null)
q.thread = null;
return s;
}
- else if (s == COMPLETING) // cannot time out yet
+ else if (s == COMPLETING)
+ // We may have already promised (via isDone) that we are done
+ // so never return empty-handed or throw InterruptedException
Thread.yield();
- else if (q == null)
+ else if (Thread.interrupted()) {
+ removeWaiter(q);
+ throw new InterruptedException();
+ }
+ else if (q == null) {
+ if (timed && nanos <= 0L)
+ return s;
q = new WaitNode();
+ }
else if (!queued)
- queued = UNSAFE.compareAndSwapObject(this, waitersOffset,
- q.next = waiters, q);
+ queued = U.compareAndSwapObject(this, WAITERS,
+ q.next = waiters, q);
else if (timed) {
- nanos = deadline - System.nanoTime();
- if (nanos <= 0L) {
- removeWaiter(q);
- return state;
+ final long parkNanos;
+ if (startTime == 0L) { // first time
+ startTime = System.nanoTime();
+ if (startTime == 0L)
+ startTime = 1L;
+ parkNanos = nanos;
+ } else {
+ long elapsed = System.nanoTime() - startTime;
+ if (elapsed >= nanos) {
+ removeWaiter(q);
+ return state;
+ }
+ parkNanos = nanos - elapsed;
}
- LockSupport.parkNanos(this, nanos);
+ // nanoTime may be slow; recheck before parking
+ if (state < COMPLETING)
+ LockSupport.parkNanos(this, parkNanos);
}
else
LockSupport.park(this);
@@ -425,8 +446,7 @@ public class FutureTask<V> implements RunnableFuture<V> {
if (pred.thread == null) // check for race
continue retry;
}
- else if (!UNSAFE.compareAndSwapObject(this, waitersOffset,
- q, s))
+ else if (!U.compareAndSwapObject(this, WAITERS, q, s))
continue retry;
}
break;
@@ -435,23 +455,25 @@ public class FutureTask<V> implements RunnableFuture<V> {
}
// Unsafe mechanics
- private static final sun.misc.Unsafe UNSAFE;
- private static final long stateOffset;
- private static final long runnerOffset;
- private static final long waitersOffset;
+ private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
+ private static final long STATE;
+ private static final long RUNNER;
+ private static final long WAITERS;
static {
try {
- UNSAFE = sun.misc.Unsafe.getUnsafe();
- Class<?> k = FutureTask.class;
- stateOffset = UNSAFE.objectFieldOffset
- (k.getDeclaredField("state"));
- runnerOffset = UNSAFE.objectFieldOffset
- (k.getDeclaredField("runner"));
- waitersOffset = UNSAFE.objectFieldOffset
- (k.getDeclaredField("waiters"));
+ STATE = U.objectFieldOffset
+ (FutureTask.class.getDeclaredField("state"));
+ RUNNER = U.objectFieldOffset
+ (FutureTask.class.getDeclaredField("runner"));
+ WAITERS = U.objectFieldOffset
+ (FutureTask.class.getDeclaredField("waiters"));
} catch (Exception e) {
throw new Error(e);
}
+
+ // Reduce the risk of rare disastrous classloading in first call to
+ // LockSupport.park: https://bugs.openjdk.java.net/browse/JDK-8074773
+ Class<?> ensureLoaded = LockSupport.class;
}
}
diff --git a/luni/src/main/java/java/util/concurrent/LinkedTransferQueue.java b/luni/src/main/java/java/util/concurrent/LinkedTransferQueue.java
index a041fb1..db48420 100644
--- a/luni/src/main/java/java/util/concurrent/LinkedTransferQueue.java
+++ b/luni/src/main/java/java/util/concurrent/LinkedTransferQueue.java
@@ -11,7 +11,6 @@ import java.util.Collection;
import java.util.Iterator;
import java.util.NoSuchElementException;
import java.util.Queue;
-import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.LockSupport;
// BEGIN android-note
@@ -76,7 +75,7 @@ public class LinkedTransferQueue<E> extends AbstractQueue<E>
*
* A FIFO dual queue may be implemented using a variation of the
* Michael & Scott (M&S) lock-free queue algorithm
- * (http://www.cs.rochester.edu/u/scott/papers/1996_PODC_queues.pdf).
+ * (http://www.cs.rochester.edu/~scott/papers/1996_PODC_queues.pdf).
* It maintains two pointer fields, "head", pointing to a
* (matched) node that in turn points to the first actual
* (unmatched) queue node (or null if empty); and "tail" that
@@ -1313,5 +1312,9 @@ public class LinkedTransferQueue<E> extends AbstractQueue<E>
} catch (Exception e) {
throw new Error(e);
}
+
+ // Reduce the risk of rare disastrous classloading in first call to
+ // LockSupport.park: https://bugs.openjdk.java.net/browse/JDK-8074773
+ Class<?> ensureLoaded = LockSupport.class;
}
}
diff --git a/luni/src/main/java/java/util/concurrent/Phaser.java b/luni/src/main/java/java/util/concurrent/Phaser.java
index a97d187..c5faf16 100644
--- a/luni/src/main/java/java/util/concurrent/Phaser.java
+++ b/luni/src/main/java/java/util/concurrent/Phaser.java
@@ -6,8 +6,6 @@
package java.util.concurrent;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicReference;
import java.util.concurrent.locks.LockSupport;
@@ -1128,5 +1126,9 @@ public class Phaser {
} catch (Exception e) {
throw new Error(e);
}
+
+ // Reduce the risk of rare disastrous classloading in first call to
+ // LockSupport.park: https://bugs.openjdk.java.net/browse/JDK-8074773
+ Class<?> ensureLoaded = LockSupport.class;
}
}
diff --git a/luni/src/main/java/java/util/concurrent/PriorityBlockingQueue.java b/luni/src/main/java/java/util/concurrent/PriorityBlockingQueue.java
index 0f9e715..40b3510 100644
--- a/luni/src/main/java/java/util/concurrent/PriorityBlockingQueue.java
+++ b/luni/src/main/java/java/util/concurrent/PriorityBlockingQueue.java
@@ -190,7 +190,7 @@ public class PriorityBlockingQueue<E> extends AbstractQueue<E>
/**
* Creates a {@code PriorityBlockingQueue} containing the elements
* in the specified collection. If the specified collection is a
- * {@link SortedSet} or a {@link PriorityQueue}, this
+ * {@link SortedSet} or a {@link PriorityQueue}, this
* priority queue will be ordered according to the same ordering.
* Otherwise, this priority queue will be ordered according to the
* {@linkplain Comparable natural ordering} of its elements.
diff --git a/luni/src/main/java/java/util/concurrent/RecursiveTask.java b/luni/src/main/java/java/util/concurrent/RecursiveTask.java
index 80baa52..d201bd6 100644
--- a/luni/src/main/java/java/util/concurrent/RecursiveTask.java
+++ b/luni/src/main/java/java/util/concurrent/RecursiveTask.java
@@ -46,6 +46,7 @@ public abstract class RecursiveTask<V> extends ForkJoinTask<V> {
/**
* The main computation performed by this task.
+ * @return the result of the computation
*/
protected abstract V compute();
diff --git a/luni/src/main/java/java/util/concurrent/ScheduledExecutorService.java b/luni/src/main/java/java/util/concurrent/ScheduledExecutorService.java
index b978fae..d5bae22 100644
--- a/luni/src/main/java/java/util/concurrent/ScheduledExecutorService.java
+++ b/luni/src/main/java/java/util/concurrent/ScheduledExecutorService.java
@@ -16,9 +16,9 @@ package java.util.concurrent;
* {@code scheduleWithFixedDelay} methods create and execute tasks
* that run periodically until cancelled.
*
- * <p>Commands submitted using the {@link Executor#execute} and
- * {@link ExecutorService} {@code submit} methods are scheduled with
- * a requested delay of zero. Zero and negative delays (but not
+ * <p>Commands submitted using the {@link Executor#execute(Runnable)}
+ * and {@link ExecutorService} {@code submit} methods are scheduled
+ * with a requested delay of zero. Zero and negative delays (but not
* periods) are also allowed in {@code schedule} methods, and are
* treated as requests for immediate execution.
*
@@ -33,7 +33,7 @@ package java.util.concurrent;
* which the task is enabled due to network time synchronization
* protocols, clock drift, or other factors.
*
- * The {@link Executors} class provides convenient factory methods for
+ * <p>The {@link Executors} class provides convenient factory methods for
* the ScheduledExecutorService implementations provided in this package.
*
* <h3>Usage Example</h3>
diff --git a/luni/src/main/java/java/util/concurrent/ScheduledThreadPoolExecutor.java b/luni/src/main/java/java/util/concurrent/ScheduledThreadPoolExecutor.java
index 483981d..d01cc33 100644
--- a/luni/src/main/java/java/util/concurrent/ScheduledThreadPoolExecutor.java
+++ b/luni/src/main/java/java/util/concurrent/ScheduledThreadPoolExecutor.java
@@ -5,7 +5,9 @@
*/
package java.util.concurrent;
+
import static java.util.concurrent.TimeUnit.NANOSECONDS;
+import static java.util.concurrent.TimeUnit.MILLISECONDS;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
@@ -17,11 +19,11 @@ import java.util.*;
/**
* A {@link ThreadPoolExecutor} that can additionally schedule
- * commands to run after a given delay, or to execute
- * periodically. This class is preferable to {@link java.util.Timer}
- * when multiple worker threads are needed, or when the additional
- * flexibility or capabilities of {@link ThreadPoolExecutor} (which
- * this class extends) are required.
+ * commands to run after a given delay, or to execute periodically.
+ * This class is preferable to {@link java.util.Timer} when multiple
+ * worker threads are needed, or when the additional flexibility or
+ * capabilities of {@link ThreadPoolExecutor} (which this class
+ * extends) are required.
*
* <p>Delayed tasks execute no sooner than they are enabled, but
* without any real-time guarantees about when, after they are
@@ -35,9 +37,9 @@ import java.util.*;
* elapses. While this enables further inspection and monitoring, it
* may also cause unbounded retention of cancelled tasks.
*
- * <p>Successive executions of a task scheduled via
- * {@code scheduleAtFixedRate} or
- * {@code scheduleWithFixedDelay} do not overlap. While different
+ * <p>Successive executions of a periodic task scheduled via
+ * {@link #scheduleAtFixedRate} or
+ * {@link #scheduleWithFixedDelay} do not overlap. While different
* executions may be performed by different threads, the effects of
* prior executions <a
* href="package-summary.html#MemoryVisibility"><i>happen-before</i></a>
@@ -132,7 +134,7 @@ public class ScheduledThreadPoolExecutor
private volatile boolean executeExistingDelayedTasksAfterShutdown = true;
/**
- * True if ScheduledFutureTask.cancel should remove from queue
+ * True if ScheduledFutureTask.cancel should remove from queue.
*/
private volatile boolean removeOnCancel = false;
@@ -159,10 +161,10 @@ public class ScheduledThreadPoolExecutor
private long time;
/**
- * Period in nanoseconds for repeating tasks. A positive
- * value indicates fixed-rate execution. A negative value
- * indicates fixed-delay execution. A value of 0 indicates a
- * non-repeating task.
+ * Period in nanoseconds for repeating tasks.
+ * A positive value indicates fixed-rate execution.
+ * A negative value indicates fixed-delay execution.
+ * A value of 0 indicates a non-repeating (one-shot) task.
*/
private final long period;
@@ -177,19 +179,21 @@ public class ScheduledThreadPoolExecutor
/**
* Creates a one-shot action with given nanoTime-based trigger time.
*/
- ScheduledFutureTask(Runnable r, V result, long ns) {
+ ScheduledFutureTask(Runnable r, V result, long triggerTime) {
super(r, result);
- this.time = ns;
+ this.time = triggerTime;
this.period = 0;
this.sequenceNumber = sequencer.getAndIncrement();
}
/**
- * Creates a periodic action with given nano time and period.
+ * Creates a periodic action with given nanoTime-based initial
+ * trigger time and period.
*/
- ScheduledFutureTask(Runnable r, V result, long ns, long period) {
+ ScheduledFutureTask(Runnable r, V result, long triggerTime,
+ long period) {
super(r, result);
- this.time = ns;
+ this.time = triggerTime;
this.period = period;
this.sequenceNumber = sequencer.getAndIncrement();
}
@@ -197,9 +201,9 @@ public class ScheduledThreadPoolExecutor
/**
* Creates a one-shot action with given nanoTime-based trigger time.
*/
- ScheduledFutureTask(Callable<V> callable, long ns) {
+ ScheduledFutureTask(Callable<V> callable, long triggerTime) {
super(callable);
- this.time = ns;
+ this.time = triggerTime;
this.period = 0;
this.sequenceNumber = sequencer.getAndIncrement();
}
@@ -389,6 +393,22 @@ public class ScheduledThreadPoolExecutor
}
/**
+ * The default keep-alive time for pool threads.
+ *
+ * Normally, this value is unused because all pool threads will be
+ * core threads, but if a user creates a pool with a corePoolSize
+ * of zero (against our advice), we keep a thread alive as long as
+ * there are queued tasks. If the keep alive time is zero (the
+ * historic value), we end up hot-spinning in getTask, wasting a
+ * CPU. But on the other hand, if we set the value too high, and
+ * users create a one-shot pool which they don't cleanly shutdown,
+ * the pool's non-daemon threads will prevent JVM termination. A
+ * small but non-zero value (relative to a JVM's lifetime) seems
+ * best.
+ */
+ private static final long DEFAULT_KEEPALIVE_MILLIS = 10L;
+
+ /**
* Creates a new {@code ScheduledThreadPoolExecutor} with the
* given core pool size.
*
@@ -397,7 +417,8 @@ public class ScheduledThreadPoolExecutor
* @throws IllegalArgumentException if {@code corePoolSize < 0}
*/
public ScheduledThreadPoolExecutor(int corePoolSize) {
- super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,
+ super(corePoolSize, Integer.MAX_VALUE,
+ DEFAULT_KEEPALIVE_MILLIS, MILLISECONDS,
new DelayedWorkQueue());
}
@@ -414,13 +435,14 @@ public class ScheduledThreadPoolExecutor
*/
public ScheduledThreadPoolExecutor(int corePoolSize,
ThreadFactory threadFactory) {
- super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,
+ super(corePoolSize, Integer.MAX_VALUE,
+ DEFAULT_KEEPALIVE_MILLIS, MILLISECONDS,
new DelayedWorkQueue(), threadFactory);
}
/**
- * Creates a new ScheduledThreadPoolExecutor with the given
- * initial parameters.
+ * Creates a new {@code ScheduledThreadPoolExecutor} with the
+ * given initial parameters.
*
* @param corePoolSize the number of threads to keep in the pool, even
* if they are idle, unless {@code allowCoreThreadTimeOut} is set
@@ -431,13 +453,14 @@ public class ScheduledThreadPoolExecutor
*/
public ScheduledThreadPoolExecutor(int corePoolSize,
RejectedExecutionHandler handler) {
- super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,
+ super(corePoolSize, Integer.MAX_VALUE,
+ DEFAULT_KEEPALIVE_MILLIS, MILLISECONDS,
new DelayedWorkQueue(), handler);
}
/**
- * Creates a new ScheduledThreadPoolExecutor with the given
- * initial parameters.
+ * Creates a new {@code ScheduledThreadPoolExecutor} with the
+ * given initial parameters.
*
* @param corePoolSize the number of threads to keep in the pool, even
* if they are idle, unless {@code allowCoreThreadTimeOut} is set
@@ -452,19 +475,20 @@ public class ScheduledThreadPoolExecutor
public ScheduledThreadPoolExecutor(int corePoolSize,
ThreadFactory threadFactory,
RejectedExecutionHandler handler) {
- super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,
+ super(corePoolSize, Integer.MAX_VALUE,
+ DEFAULT_KEEPALIVE_MILLIS, MILLISECONDS,
new DelayedWorkQueue(), threadFactory, handler);
}
/**
- * Returns the trigger time of a delayed action.
+ * Returns the nanoTime-based trigger time of a delayed action.
*/
private long triggerTime(long delay, TimeUnit unit) {
return triggerTime(unit.toNanos((delay < 0) ? 0 : delay));
}
/**
- * Returns the trigger time of a delayed action.
+ * Returns the nanoTime-based trigger time of a delayed action.
*/
long triggerTime(long delay) {
return now() +
@@ -497,7 +521,7 @@ public class ScheduledThreadPoolExecutor
TimeUnit unit) {
if (command == null || unit == null)
throw new NullPointerException();
- RunnableScheduledFuture<?> t = decorateTask(command,
+ RunnableScheduledFuture<Void> t = decorateTask(command,
new ScheduledFutureTask<Void>(command, null,
triggerTime(delay, unit)));
delayedExecute(t);
@@ -725,6 +749,7 @@ public class ScheduledThreadPoolExecutor
* {@code true}, future executions of existing periodic tasks will
* be cancelled.
*/
+ // android-note: Removed "throws SecurityException" doc.
public void shutdown() {
super.shutdown();
}
@@ -744,23 +769,28 @@ public class ScheduledThreadPoolExecutor
* fails to respond to interrupts may never terminate.
*
* @return list of tasks that never commenced execution.
- * Each element of this list is a {@link ScheduledFuture},
- * including those tasks submitted using {@code execute},
- * which are for scheduling purposes used as the basis of a
- * zero-delay {@code ScheduledFuture}.
+ * Each element of this list is a {@link ScheduledFuture}.
+ * For tasks submitted via one of the {@code schedule}
+ * methods, the element will be identical to the returned
+ * {@code ScheduledFuture}. For tasks submitted using
+ * {@link #execute}, the element will be a zero-delay {@code
+ * ScheduledFuture}.
*/
+ // android-note: Removed "throws SecurityException" doc.
public List<Runnable> shutdownNow() {
return super.shutdownNow();
}
/**
- * Returns the task queue used by this executor. Each element of
- * this queue is a {@link ScheduledFuture}, including those
- * tasks submitted using {@code execute} which are for scheduling
- * purposes used as the basis of a zero-delay
- * {@code ScheduledFuture}. Iteration over this queue is
- * <em>not</em> guaranteed to traverse tasks in the order in
- * which they will execute.
+ * Returns the task queue used by this executor.
+ * Each element of this list is a {@link ScheduledFuture}.
+ * For tasks submitted via one of the {@code schedule} methods, the
+ * element will be identical to the returned {@code ScheduledFuture}.
+ * For tasks submitted using {@link #execute}, the element will be a
+ * zero-delay {@code ScheduledFuture}.
+ *
+ * <p>Iteration over this queue is <em>not</em> guaranteed to traverse
+ * tasks in the order in which they will execute.
*
* @return the task queue
*/
@@ -803,7 +833,7 @@ public class ScheduledThreadPoolExecutor
private RunnableScheduledFuture<?>[] queue =
new RunnableScheduledFuture<?>[INITIAL_CAPACITY];
private final ReentrantLock lock = new ReentrantLock();
- private int size = 0;
+ private int size;
/**
* Thread designated to wait for the task at the head of the
@@ -821,7 +851,7 @@ public class ScheduledThreadPoolExecutor
* signalled. So waiting threads must be prepared to acquire
* and lose leadership while waiting.
*/
- private Thread leader = null;
+ private Thread leader;
/**
* Condition signalled when a newer task becomes available at the
@@ -1220,11 +1250,11 @@ public class ScheduledThreadPoolExecutor
* Snapshot iterator that works off copy of underlying q array.
*/
private class Itr implements Iterator<Runnable> {
- final RunnableScheduledFuture[] array;
+ final RunnableScheduledFuture<?>[] array;
int cursor = 0; // index of next element to return
int lastRet = -1; // index of last element, or -1 if no such
- Itr(RunnableScheduledFuture[] array) {
+ Itr(RunnableScheduledFuture<?>[] array) {
this.array = array;
}
diff --git a/luni/src/main/java/java/util/concurrent/Semaphore.java b/luni/src/main/java/java/util/concurrent/Semaphore.java
index 9ee18a8..b4b7edd 100644
--- a/luni/src/main/java/java/util/concurrent/Semaphore.java
+++ b/luni/src/main/java/java/util/concurrent/Semaphore.java
@@ -5,6 +5,7 @@
*/
package java.util.concurrent;
+
import java.util.Collection;
import java.util.concurrent.locks.AbstractQueuedSynchronizer;
diff --git a/luni/src/main/java/java/util/concurrent/SynchronousQueue.java b/luni/src/main/java/java/util/concurrent/SynchronousQueue.java
index ea6b3d1..69452af 100644
--- a/luni/src/main/java/java/util/concurrent/SynchronousQueue.java
+++ b/luni/src/main/java/java/util/concurrent/SynchronousQueue.java
@@ -6,6 +6,7 @@
*/
package java.util.concurrent;
+
import java.util.concurrent.locks.LockSupport;
import java.util.concurrent.locks.ReentrantLock;
import java.util.*;
@@ -1057,7 +1058,7 @@ public class SynchronousQueue<E> extends AbstractQueue<E>
}
/**
- * Sets the zeroeth element of the specified array to {@code null}
+ * Sets the zeroth element of the specified array to {@code null}
* (if the array has non-zero length) and returns it.
*
* @param a the array
@@ -1150,7 +1151,7 @@ public class SynchronousQueue<E> extends AbstractQueue<E>
/**
* Reconstitutes this queue from a stream (that is, deserializes it).
*/
- private void readObject(final java.io.ObjectInputStream s)
+ private void readObject(java.io.ObjectInputStream s)
throws java.io.IOException, ClassNotFoundException {
s.defaultReadObject();
if (waitingProducers instanceof FifoWaitQueue)
@@ -1172,4 +1173,9 @@ public class SynchronousQueue<E> extends AbstractQueue<E>
}
}
+ static {
+ // Reduce the risk of rare disastrous classloading in first call to
+ // LockSupport.park: https://bugs.openjdk.java.net/browse/JDK-8074773
+ Class<?> ensureLoaded = LockSupport.class;
+ }
}
diff --git a/luni/src/main/java/java/util/concurrent/ThreadLocalRandom.java b/luni/src/main/java/java/util/concurrent/ThreadLocalRandom.java
index 5baf75f..b007af2 100644
--- a/luni/src/main/java/java/util/concurrent/ThreadLocalRandom.java
+++ b/luni/src/main/java/java/util/concurrent/ThreadLocalRandom.java
@@ -107,9 +107,9 @@ public class ThreadLocalRandom extends Random {
*
* @param least the least value returned
* @param bound the upper bound (exclusive)
+ * @return the next value
* @throws IllegalArgumentException if least greater than or equal
* to bound
- * @return the next value
*/
public int nextInt(int least, int bound) {
if (least >= bound)
@@ -172,7 +172,7 @@ public class ThreadLocalRandom extends Random {
* @throws IllegalArgumentException if n is not positive
*/
public double nextDouble(double n) {
- if (n <= 0)
+ if (!(n > 0))
throw new IllegalArgumentException("n must be positive");
return nextDouble() * n;
}
diff --git a/luni/src/main/java/java/util/concurrent/ThreadPoolExecutor.java b/luni/src/main/java/java/util/concurrent/ThreadPoolExecutor.java
index 9586293..c484920 100644
--- a/luni/src/main/java/java/util/concurrent/ThreadPoolExecutor.java
+++ b/luni/src/main/java/java/util/concurrent/ThreadPoolExecutor.java
@@ -5,6 +5,7 @@
*/
package java.util.concurrent;
+
import java.util.concurrent.locks.AbstractQueuedSynchronizer;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
@@ -582,7 +583,7 @@ public class ThreadPoolExecutor extends AbstractExecutorService {
this.thread = getThreadFactory().newThread(this);
}
- /** Delegates main run loop to outer runWorker */
+ /** Delegates main run loop to outer runWorker. */
public void run() {
runWorker(this);
}
@@ -1348,6 +1349,7 @@ public class ThreadPoolExecutor extends AbstractExecutorService {
* complete execution. Use {@link #awaitTermination awaitTermination}
* to do that.
*/
+ // android-note: Removed @throws SecurityException
public void shutdown() {
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
@@ -1377,6 +1379,7 @@ public class ThreadPoolExecutor extends AbstractExecutorService {
* cancels tasks via {@link Thread#interrupt}, so any task that
* fails to respond to interrupts may never terminate.
*/
+ // android-note: Removed @throws SecurityException
public List<Runnable> shutdownNow() {
List<Runnable> tasks;
final ReentrantLock mainLock = this.mainLock;
diff --git a/luni/src/main/java/java/util/concurrent/TimeUnit.java b/luni/src/main/java/java/util/concurrent/TimeUnit.java
index eb2c495..8e6a5f7 100644
--- a/luni/src/main/java/java/util/concurrent/TimeUnit.java
+++ b/luni/src/main/java/java/util/concurrent/TimeUnit.java
@@ -40,6 +40,9 @@ package java.util.concurrent;
* @author Doug Lea
*/
public enum TimeUnit {
+ /**
+ * Time unit representing one thousandth of a microsecond
+ */
NANOSECONDS {
public long toNanos(long d) { return d; }
public long toMicros(long d) { return d/(C1/C0); }
@@ -51,6 +54,10 @@ public enum TimeUnit {
public long convert(long d, TimeUnit u) { return u.toNanos(d); }
int excessNanos(long d, long m) { return (int)(d - (m*C2)); }
},
+
+ /**
+ * Time unit representing one thousandth of a millisecond
+ */
MICROSECONDS {
public long toNanos(long d) { return x(d, C1/C0, MAX/(C1/C0)); }
public long toMicros(long d) { return d; }
@@ -62,6 +69,10 @@ public enum TimeUnit {
public long convert(long d, TimeUnit u) { return u.toMicros(d); }
int excessNanos(long d, long m) { return (int)((d*C1) - (m*C2)); }
},
+
+ /**
+ * Time unit representing one thousandth of a second
+ */
MILLISECONDS {
public long toNanos(long d) { return x(d, C2/C0, MAX/(C2/C0)); }
public long toMicros(long d) { return x(d, C2/C1, MAX/(C2/C1)); }
@@ -73,6 +84,10 @@ public enum TimeUnit {
public long convert(long d, TimeUnit u) { return u.toMillis(d); }
int excessNanos(long d, long m) { return 0; }
},
+
+ /**
+ * Time unit representing one second
+ */
SECONDS {
public long toNanos(long d) { return x(d, C3/C0, MAX/(C3/C0)); }
public long toMicros(long d) { return x(d, C3/C1, MAX/(C3/C1)); }
@@ -84,6 +99,11 @@ public enum TimeUnit {
public long convert(long d, TimeUnit u) { return u.toSeconds(d); }
int excessNanos(long d, long m) { return 0; }
},
+
+ /**
+ * Time unit representing sixty seconds
+ * @since 1.6
+ */
MINUTES {
public long toNanos(long d) { return x(d, C4/C0, MAX/(C4/C0)); }
public long toMicros(long d) { return x(d, C4/C1, MAX/(C4/C1)); }
@@ -95,6 +115,11 @@ public enum TimeUnit {
public long convert(long d, TimeUnit u) { return u.toMinutes(d); }
int excessNanos(long d, long m) { return 0; }
},
+
+ /**
+ * Time unit representing sixty minutes
+ * @since 1.6
+ */
HOURS {
public long toNanos(long d) { return x(d, C5/C0, MAX/(C5/C0)); }
public long toMicros(long d) { return x(d, C5/C1, MAX/(C5/C1)); }
@@ -106,6 +131,11 @@ public enum TimeUnit {
public long convert(long d, TimeUnit u) { return u.toHours(d); }
int excessNanos(long d, long m) { return 0; }
},
+
+ /**
+ * Time unit representing twenty four hours
+ * @since 1.6
+ */
DAYS {
public long toNanos(long d) { return x(d, C6/C0, MAX/(C6/C0)); }
public long toMicros(long d) { return x(d, C6/C1, MAX/(C6/C1)); }
@@ -145,14 +175,13 @@ public enum TimeUnit {
// etc. are not declared abstract but otherwise act as abstract methods.
/**
- * Convert the given time duration in the given unit to this
- * unit. Conversions from finer to coarser granularities
- * truncate, so lose precision. For example converting
- * {@code 999} milliseconds to seconds results in
- * {@code 0}. Conversions from coarser to finer granularities
- * with arguments that would numerically overflow saturate to
- * {@code Long.MIN_VALUE} if negative or {@code Long.MAX_VALUE}
- * if positive.
+ * Converts the given time duration in the given unit to this unit.
+ * Conversions from finer to coarser granularities truncate, so
+ * lose precision. For example, converting {@code 999} milliseconds
+ * to seconds results in {@code 0}. Conversions from coarser to
+ * finer granularities with arguments that would numerically
+ * overflow saturate to {@code Long.MIN_VALUE} if negative or
+ * {@code Long.MAX_VALUE} if positive.
*
* <p>For example, to convert 10 minutes to milliseconds, use:
* {@code TimeUnit.MILLISECONDS.convert(10L, TimeUnit.MINUTES)}
@@ -168,60 +197,60 @@ public enum TimeUnit {
}
/**
- * Equivalent to {@code NANOSECONDS.convert(duration, this)}.
+ * Equivalent to
+ * {@link #convert(long, TimeUnit) NANOSECONDS.convert(duration, this)}.
* @param duration the duration
* @return the converted duration,
* or {@code Long.MIN_VALUE} if conversion would negatively
* overflow, or {@code Long.MAX_VALUE} if it would positively overflow.
- * @see #convert
*/
public long toNanos(long duration) {
throw new AbstractMethodError();
}
/**
- * Equivalent to {@code MICROSECONDS.convert(duration, this)}.
+ * Equivalent to
+ * {@link #convert(long, TimeUnit) MICROSECONDS.convert(duration, this)}.
* @param duration the duration
* @return the converted duration,
* or {@code Long.MIN_VALUE} if conversion would negatively
* overflow, or {@code Long.MAX_VALUE} if it would positively overflow.
- * @see #convert
*/
public long toMicros(long duration) {
throw new AbstractMethodError();
}
/**
- * Equivalent to {@code MILLISECONDS.convert(duration, this)}.
+ * Equivalent to
+ * {@link #convert(long, TimeUnit) MILLISECONDS.convert(duration, this)}.
* @param duration the duration
* @return the converted duration,
* or {@code Long.MIN_VALUE} if conversion would negatively
* overflow, or {@code Long.MAX_VALUE} if it would positively overflow.
- * @see #convert
*/
public long toMillis(long duration) {
throw new AbstractMethodError();
}
/**
- * Equivalent to {@code SECONDS.convert(duration, this)}.
+ * Equivalent to
+ * {@link #convert(long, TimeUnit) SECONDS.convert(duration, this)}.
* @param duration the duration
* @return the converted duration,
* or {@code Long.MIN_VALUE} if conversion would negatively
* overflow, or {@code Long.MAX_VALUE} if it would positively overflow.
- * @see #convert
*/
public long toSeconds(long duration) {
throw new AbstractMethodError();
}
/**
- * Equivalent to {@code MINUTES.convert(duration, this)}.
+ * Equivalent to
+ * {@link #convert(long, TimeUnit) MINUTES.convert(duration, this)}.
* @param duration the duration
* @return the converted duration,
* or {@code Long.MIN_VALUE} if conversion would negatively
* overflow, or {@code Long.MAX_VALUE} if it would positively overflow.
- * @see #convert
* @since 1.6
*/
public long toMinutes(long duration) {
@@ -229,12 +258,12 @@ public enum TimeUnit {
}
/**
- * Equivalent to {@code HOURS.convert(duration, this)}.
+ * Equivalent to
+ * {@link #convert(long, TimeUnit) HOURS.convert(duration, this)}.
* @param duration the duration
* @return the converted duration,
* or {@code Long.MIN_VALUE} if conversion would negatively
* overflow, or {@code Long.MAX_VALUE} if it would positively overflow.
- * @see #convert
* @since 1.6
*/
public long toHours(long duration) {
@@ -242,10 +271,10 @@ public enum TimeUnit {
}
/**
- * Equivalent to {@code DAYS.convert(duration, this)}.
+ * Equivalent to
+ * {@link #convert(long, TimeUnit) DAYS.convert(duration, this)}.
* @param duration the duration
* @return the converted duration
- * @see #convert
* @since 1.6
*/
public long toDays(long duration) {
diff --git a/luni/src/main/java/java/util/concurrent/atomic/AtomicBoolean.java b/luni/src/main/java/java/util/concurrent/atomic/AtomicBoolean.java
index 13b12aa..f51e6af 100644
--- a/luni/src/main/java/java/util/concurrent/atomic/AtomicBoolean.java
+++ b/luni/src/main/java/java/util/concurrent/atomic/AtomicBoolean.java
@@ -5,6 +5,7 @@
*/
package java.util.concurrent.atomic;
+
import sun.misc.Unsafe;
/**
diff --git a/luni/src/main/java/java/util/concurrent/atomic/AtomicInteger.java b/luni/src/main/java/java/util/concurrent/atomic/AtomicInteger.java
index d67b20a..8a15298 100644
--- a/luni/src/main/java/java/util/concurrent/atomic/AtomicInteger.java
+++ b/luni/src/main/java/java/util/concurrent/atomic/AtomicInteger.java
@@ -5,6 +5,7 @@
*/
package java.util.concurrent.atomic;
+
import sun.misc.Unsafe;
/**
diff --git a/luni/src/main/java/java/util/concurrent/atomic/AtomicIntegerArray.java b/luni/src/main/java/java/util/concurrent/atomic/AtomicIntegerArray.java
index 1f6980d..fd492d1 100644
--- a/luni/src/main/java/java/util/concurrent/atomic/AtomicIntegerArray.java
+++ b/luni/src/main/java/java/util/concurrent/atomic/AtomicIntegerArray.java
@@ -5,6 +5,7 @@
*/
package java.util.concurrent.atomic;
+
import sun.misc.Unsafe;
/**
diff --git a/luni/src/main/java/java/util/concurrent/atomic/AtomicIntegerFieldUpdater.java b/luni/src/main/java/java/util/concurrent/atomic/AtomicIntegerFieldUpdater.java
index 6067152..4354cb6 100644
--- a/luni/src/main/java/java/util/concurrent/atomic/AtomicIntegerFieldUpdater.java
+++ b/luni/src/main/java/java/util/concurrent/atomic/AtomicIntegerFieldUpdater.java
@@ -10,6 +10,9 @@ import dalvik.system.VMStack; // android-added
import sun.misc.Unsafe;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
+import java.security.AccessController;
+import java.security.PrivilegedExceptionAction;
+import java.security.PrivilegedActionException;
/**
* A reflection-based utility that enables atomic updates to
@@ -243,7 +246,7 @@ public abstract class AtomicIntegerFieldUpdater<T> {
private final Class<T> tclass;
private final Class<?> cclass;
- AtomicIntegerFieldUpdaterImpl(Class<T> tclass, String fieldName) {
+ AtomicIntegerFieldUpdaterImpl(final Class<T> tclass, final String fieldName) {
final Field field;
final Class<?> caller;
final int modifiers;
diff --git a/luni/src/main/java/java/util/concurrent/atomic/AtomicLong.java b/luni/src/main/java/java/util/concurrent/atomic/AtomicLong.java
index 278c5b5..ab2961a 100644
--- a/luni/src/main/java/java/util/concurrent/atomic/AtomicLong.java
+++ b/luni/src/main/java/java/util/concurrent/atomic/AtomicLong.java
@@ -5,6 +5,7 @@
*/
package java.util.concurrent.atomic;
+
import sun.misc.Unsafe;
/**
diff --git a/luni/src/main/java/java/util/concurrent/atomic/AtomicLongArray.java b/luni/src/main/java/java/util/concurrent/atomic/AtomicLongArray.java
index 2e8c2b7..b7f3d1e 100644
--- a/luni/src/main/java/java/util/concurrent/atomic/AtomicLongArray.java
+++ b/luni/src/main/java/java/util/concurrent/atomic/AtomicLongArray.java
@@ -5,6 +5,7 @@
*/
package java.util.concurrent.atomic;
+
import sun.misc.Unsafe;
/**
diff --git a/luni/src/main/java/java/util/concurrent/atomic/AtomicLongFieldUpdater.java b/luni/src/main/java/java/util/concurrent/atomic/AtomicLongFieldUpdater.java
index 0096a6b..715788c 100644
--- a/luni/src/main/java/java/util/concurrent/atomic/AtomicLongFieldUpdater.java
+++ b/luni/src/main/java/java/util/concurrent/atomic/AtomicLongFieldUpdater.java
@@ -243,7 +243,7 @@ public abstract class AtomicLongFieldUpdater<T> {
private final Class<T> tclass;
private final Class<?> cclass;
- CASUpdater(Class<T> tclass, String fieldName) {
+ CASUpdater(final Class<T> tclass, final String fieldName) {
final Field field;
final Class<?> caller;
final int modifiers;
@@ -337,7 +337,7 @@ public abstract class AtomicLongFieldUpdater<T> {
private final Class<T> tclass;
private final Class<?> cclass;
- LockedUpdater(Class<T> tclass, String fieldName) {
+ LockedUpdater(final Class<T> tclass, final String fieldName) {
Field field = null;
Class<?> caller = null;
int modifiers = 0;
diff --git a/luni/src/main/java/java/util/concurrent/atomic/AtomicMarkableReference.java b/luni/src/main/java/java/util/concurrent/atomic/AtomicMarkableReference.java
index 1257be0..18d148f 100644
--- a/luni/src/main/java/java/util/concurrent/atomic/AtomicMarkableReference.java
+++ b/luni/src/main/java/java/util/concurrent/atomic/AtomicMarkableReference.java
@@ -68,7 +68,7 @@ public class AtomicMarkableReference<V> {
* Typical usage is {@code boolean[1] holder; ref = v.get(holder); }.
*
* @param markHolder an array of size of at least one. On return,
- * {@code markholder[0]} will hold the value of the mark.
+ * {@code markHolder[0]} will hold the value of the mark.
* @return the current value of the reference
*/
public V get(boolean[] markHolder) {
diff --git a/luni/src/main/java/java/util/concurrent/atomic/AtomicReference.java b/luni/src/main/java/java/util/concurrent/atomic/AtomicReference.java
index 98b402a..7ea6066 100644
--- a/luni/src/main/java/java/util/concurrent/atomic/AtomicReference.java
+++ b/luni/src/main/java/java/util/concurrent/atomic/AtomicReference.java
@@ -5,6 +5,7 @@
*/
package java.util.concurrent.atomic;
+
import sun.misc.Unsafe;
/**
diff --git a/luni/src/main/java/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.java b/luni/src/main/java/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.java
index eb2d73e..4b5e59c 100644
--- a/luni/src/main/java/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.java
+++ b/luni/src/main/java/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.java
@@ -5,6 +5,7 @@
*/
package java.util.concurrent.atomic;
+
import dalvik.system.VMStack; // android-added
import sun.misc.Unsafe;
import java.lang.reflect.Field;
@@ -27,7 +28,7 @@ import java.lang.reflect.Modifier;
* private static AtomicReferenceFieldUpdater<Node, Node> rightUpdater =
* AtomicReferenceFieldUpdater.newUpdater(Node.class, Node.class, "right");
*
- * Node getLeft() { return left; }
+ * Node getLeft() { return left; }
* boolean compareAndSetLeft(Node expect, Node update) {
* return leftUpdater.compareAndSet(this, expect, update);
* }
@@ -63,10 +64,11 @@ public abstract class AtomicReferenceFieldUpdater<T,V> {
* or the field is inaccessible to the caller according to Java language
* access control
*/
- public static <U, W> AtomicReferenceFieldUpdater<U,W> newUpdater(Class<U> tclass, Class<W> vclass, String fieldName) {
- return new AtomicReferenceFieldUpdaterImpl<U,W>(tclass,
- vclass,
- fieldName);
+ public static <U,W> AtomicReferenceFieldUpdater<U,W> newUpdater(Class<U> tclass,
+ Class<W> vclass,
+ String fieldName) {
+ return new AtomicReferenceFieldUpdaterImpl<U,W>
+ (tclass, vclass, fieldName);
}
/**
diff --git a/luni/src/main/java/java/util/concurrent/atomic/AtomicStampedReference.java b/luni/src/main/java/java/util/concurrent/atomic/AtomicStampedReference.java
index b93a6f3..1449856 100644
--- a/luni/src/main/java/java/util/concurrent/atomic/AtomicStampedReference.java
+++ b/luni/src/main/java/java/util/concurrent/atomic/AtomicStampedReference.java
@@ -68,7 +68,7 @@ public class AtomicStampedReference<V> {
* Typical usage is {@code int[1] holder; ref = v.get(holder); }.
*
* @param stampHolder an array of size of at least one. On return,
- * {@code stampholder[0]} will hold the value of the stamp.
+ * {@code stampHolder[0]} will hold the value of the stamp.
* @return the current value of the reference
*/
public V get(int[] stampHolder) {
diff --git a/luni/src/main/java/java/util/concurrent/locks/AbstractOwnableSynchronizer.java b/luni/src/main/java/java/util/concurrent/locks/AbstractOwnableSynchronizer.java
index fa01824..66a2f8e 100644
--- a/luni/src/main/java/java/util/concurrent/locks/AbstractOwnableSynchronizer.java
+++ b/luni/src/main/java/java/util/concurrent/locks/AbstractOwnableSynchronizer.java
@@ -35,20 +35,20 @@ public abstract class AbstractOwnableSynchronizer
private transient Thread exclusiveOwnerThread;
/**
- * Sets the thread that currently owns exclusive access. A
- * {@code null} argument indicates that no thread owns access.
+ * Sets the thread that currently owns exclusive access.
+ * A {@code null} argument indicates that no thread owns access.
* This method does not otherwise impose any synchronization or
* {@code volatile} field accesses.
+ * @param thread the owner thread
*/
- protected final void setExclusiveOwnerThread(Thread t) {
- exclusiveOwnerThread = t;
+ protected final void setExclusiveOwnerThread(Thread thread) {
+ exclusiveOwnerThread = thread;
}
/**
- * Returns the thread last set by
- * {@code setExclusiveOwnerThread}, or {@code null} if never
- * set. This method does not otherwise impose any synchronization
- * or {@code volatile} field accesses.
+ * Returns the thread last set by {@code setExclusiveOwnerThread},
+ * or {@code null} if never set. This method does not otherwise
+ * impose any synchronization or {@code volatile} field accesses.
* @return the owner thread
*/
protected final Thread getExclusiveOwnerThread() {
diff --git a/luni/src/main/java/java/util/concurrent/locks/AbstractQueuedLongSynchronizer.java b/luni/src/main/java/java/util/concurrent/locks/AbstractQueuedLongSynchronizer.java
index 37aa9d0..47a02a9 100644
--- a/luni/src/main/java/java/util/concurrent/locks/AbstractQueuedLongSynchronizer.java
+++ b/luni/src/main/java/java/util/concurrent/locks/AbstractQueuedLongSynchronizer.java
@@ -5,6 +5,7 @@
*/
package java.util.concurrent.locks;
+
import java.util.concurrent.TimeUnit;
import java.util.ArrayList;
import java.util.Collection;
@@ -227,7 +228,7 @@ public abstract class AbstractQueuedLongSynchronizer
Node nextWaiter;
/**
- * @return true if node is waiting in shared mode
+ * Returns true if node is waiting in shared mode.
*/
final boolean isShared() {
return nextWaiter == SHARED;
@@ -403,9 +404,9 @@ public abstract class AbstractQueuedLongSynchronizer
Node s = node.next;
if (s == null || s.waitStatus > 0) {
s = null;
- for (Node t = tail; t != null && t != node; t = t.prev)
- if (t.waitStatus <= 0)
- s = t;
+ for (Node p = tail; p != null && p != node; p = p.prev)
+ if (p.waitStatus <= 0)
+ s = p;
}
if (s != null)
LockSupport.unpark(s.thread);
@@ -1397,13 +1398,13 @@ public abstract class AbstractQueuedLongSynchronizer
* @return true if present
*/
private boolean findNodeFromTail(Node node) {
- Node t = tail;
+ Node p = tail;
for (;;) {
- if (t == node)
+ if (p == node)
return true;
- if (t == null)
+ if (p == null)
return false;
- t = t.prev;
+ p = p.prev;
}
}
@@ -1814,6 +1815,7 @@ public abstract class AbstractQueuedLongSynchronizer
throws InterruptedException {
if (Thread.interrupted())
throw new InterruptedException();
+ long initialNanos = nanosTimeout;
Node node = addConditionWaiter();
long savedState = fullyRelease(node);
final long deadline = System.nanoTime() + nanosTimeout;
@@ -1835,7 +1837,8 @@ public abstract class AbstractQueuedLongSynchronizer
unlinkCancelledWaiters();
if (interruptMode != 0)
reportInterruptAfterWait(interruptMode);
- return deadline - System.nanoTime();
+ long remaining = deadline - System.nanoTime(); // avoid overflow
+ return (remaining < initialNanos) ? remaining : Long.MIN_VALUE;
}
/**
@@ -2027,6 +2030,10 @@ public abstract class AbstractQueuedLongSynchronizer
(Node.class.getDeclaredField("next"));
} catch (Exception ex) { throw new Error(ex); }
+
+ // Reduce the risk of rare disastrous classloading in first call to
+ // LockSupport.park: https://bugs.openjdk.java.net/browse/JDK-8074773
+ Class<?> ensureLoaded = LockSupport.class;
}
/**
diff --git a/luni/src/main/java/java/util/concurrent/locks/AbstractQueuedSynchronizer.java b/luni/src/main/java/java/util/concurrent/locks/AbstractQueuedSynchronizer.java
index e711da5..bfe88e5 100644
--- a/luni/src/main/java/java/util/concurrent/locks/AbstractQueuedSynchronizer.java
+++ b/luni/src/main/java/java/util/concurrent/locks/AbstractQueuedSynchronizer.java
@@ -5,6 +5,7 @@
*/
package java.util.concurrent.locks;
+
import java.util.concurrent.TimeUnit;
import java.util.ArrayList;
import java.util.Collection;
@@ -128,15 +129,11 @@ import sun.misc.Unsafe;
* others that are blocked and queued. However, you can, if desired,
* define {@code tryAcquire} and/or {@code tryAcquireShared} to
* disable barging by internally invoking one or more of the inspection
- * methods. In particular, a strict FIFO lock can define
- * {@code tryAcquire} to immediately return {@code false} if {@link
- * #getFirstQueuedThread} does not return the current thread. A
- * normally preferable non-strict fair version can immediately return
- * {@code false} only if {@link #hasQueuedThreads} returns
- * {@code true} and {@code getFirstQueuedThread} is not the current
- * thread; or equivalently, that {@code getFirstQueuedThread} is both
- * non-null and not the current thread. Further variations are
- * possible.
+ * methods, thereby providing a <em>fair</em> FIFO acquisition order.
+ * In particular, most fair synchronizers can define {@code tryAcquire}
+ * to return {@code false} if {@code hasQueuedPredecessors} (a method
+ * specifically designed to be used by fair synchronizers) returns
+ * {@code true}. Other variations are possible.
*
* <p>Throughput and scalability are generally highest for the
* default barging (also known as <em>greedy</em>,
@@ -1461,7 +1458,7 @@ public abstract class AbstractQueuedSynchronizer
* due to the queue being empty.
*
* <p>This method is designed to be used by a fair synchronizer to
- * avoid <a href="AbstractQueuedSynchronizer#barging">barging</a>.
+ * avoid <a href="AbstractQueuedSynchronizer.html#barging">barging</a>.
* Such a synchronizer's {@link #tryAcquire} method should return
* {@code false}, and its {@link #tryAcquireShared} method should
* return a negative value, if this method returns {@code true}
@@ -2042,6 +2039,7 @@ public abstract class AbstractQueuedSynchronizer
throws InterruptedException {
if (Thread.interrupted())
throw new InterruptedException();
+ long initialNanos = nanosTimeout;
Node node = addConditionWaiter();
int savedState = fullyRelease(node);
final long deadline = System.nanoTime() + nanosTimeout;
@@ -2063,7 +2061,8 @@ public abstract class AbstractQueuedSynchronizer
unlinkCancelledWaiters();
if (interruptMode != 0)
reportInterruptAfterWait(interruptMode);
- return deadline - System.nanoTime();
+ long remaining = deadline - System.nanoTime(); // avoid overflow
+ return (remaining < initialNanos) ? remaining : Long.MIN_VALUE;
}
/**
@@ -2255,6 +2254,10 @@ public abstract class AbstractQueuedSynchronizer
(Node.class.getDeclaredField("next"));
} catch (Exception ex) { throw new Error(ex); }
+
+ // Reduce the risk of rare disastrous classloading in first call to
+ // LockSupport.park: https://bugs.openjdk.java.net/browse/JDK-8074773
+ Class<?> ensureLoaded = LockSupport.class;
}
/**
diff --git a/luni/src/main/java/java/util/concurrent/locks/Condition.java b/luni/src/main/java/java/util/concurrent/locks/Condition.java
index 522e9e2..11a7090 100644
--- a/luni/src/main/java/java/util/concurrent/locks/Condition.java
+++ b/luni/src/main/java/java/util/concurrent/locks/Condition.java
@@ -5,6 +5,7 @@
*/
package java.util.concurrent.locks;
+
import java.util.concurrent.TimeUnit;
import java.util.Date;
diff --git a/luni/src/main/java/java/util/concurrent/locks/Lock.java b/luni/src/main/java/java/util/concurrent/locks/Lock.java
index 6eeb236..a7ca001 100644
--- a/luni/src/main/java/java/util/concurrent/locks/Lock.java
+++ b/luni/src/main/java/java/util/concurrent/locks/Lock.java
@@ -5,6 +5,7 @@
*/
package java.util.concurrent.locks;
+
import java.util.concurrent.TimeUnit;
/**
diff --git a/luni/src/main/java/java/util/concurrent/locks/LockSupport.java b/luni/src/main/java/java/util/concurrent/locks/LockSupport.java
index 875b2bf..089d818 100644
--- a/luni/src/main/java/java/util/concurrent/locks/LockSupport.java
+++ b/luni/src/main/java/java/util/concurrent/locks/LockSupport.java
@@ -5,6 +5,7 @@
*/
package java.util.concurrent.locks;
+
import sun.misc.Unsafe;
/**
diff --git a/luni/src/main/java/java/util/concurrent/locks/ReentrantLock.java b/luni/src/main/java/java/util/concurrent/locks/ReentrantLock.java
index bde4741..3654248 100644
--- a/luni/src/main/java/java/util/concurrent/locks/ReentrantLock.java
+++ b/luni/src/main/java/java/util/concurrent/locks/ReentrantLock.java
@@ -5,6 +5,7 @@
*/
package java.util.concurrent.locks;
+
import java.util.concurrent.TimeUnit;
import java.util.Collection;
diff --git a/luni/src/main/java/java/util/concurrent/locks/ReentrantReadWriteLock.java b/luni/src/main/java/java/util/concurrent/locks/ReentrantReadWriteLock.java
index 2d3c65d..cc7ba4c 100644
--- a/luni/src/main/java/java/util/concurrent/locks/ReentrantReadWriteLock.java
+++ b/luni/src/main/java/java/util/concurrent/locks/ReentrantReadWriteLock.java
@@ -5,6 +5,7 @@
*/
package java.util.concurrent.locks;
+
import java.util.concurrent.TimeUnit;
import java.util.Collection;
@@ -236,14 +237,14 @@ public class ReentrantReadWriteLock
static final int MAX_COUNT = (1 << SHARED_SHIFT) - 1;
static final int EXCLUSIVE_MASK = (1 << SHARED_SHIFT) - 1;
- /** Returns the number of shared holds represented in count */
+ /** Returns the number of shared holds represented in count. */
static int sharedCount(int c) { return c >>> SHARED_SHIFT; }
- /** Returns the number of exclusive holds represented in count */
+ /** Returns the number of exclusive holds represented in count. */
static int exclusiveCount(int c) { return c & EXCLUSIVE_MASK; }
/**
* A counter for per-thread read hold counts.
- * Maintained as a ThreadLocal; cached in cachedHoldCounter
+ * Maintained as a ThreadLocal; cached in cachedHoldCounter.
*/
static final class HoldCounter {
int count = 0;
@@ -303,7 +304,7 @@ public class ReentrantReadWriteLock
* <p>This allows tracking of read holds for uncontended read
* locks to be very cheap.
*/
- private transient Thread firstReader = null;
+ private transient Thread firstReader;
private transient int firstReaderHoldCount;
Sync() {
diff --git a/luni/src/main/java/java/util/concurrent/package-info.java b/luni/src/main/java/java/util/concurrent/package-info.java
index 51a29e8..afc8ca4 100644
--- a/luni/src/main/java/java/util/concurrent/package-info.java
+++ b/luni/src/main/java/java/util/concurrent/package-info.java
@@ -4,10 +4,6 @@
* http://creativecommons.org/publicdomain/zero/1.0/
*/
-// BEGIN android-note
-// omit links to ForkJoinPool, ForkJoinTask, LinkedTransferQueue, Phaser, TransferQueue
-// END android-note
-
/**
* Utility classes commonly useful in concurrent programming. This
* package includes a few small standardized extensible frameworks, as
@@ -67,11 +63,20 @@
* assists in coordinating the processing of groups of
* asynchronous tasks.
*
+ * <p>Class {@link java.util.concurrent.ForkJoinPool} provides an
+ * Executor primarily designed for processing instances of {@link
+ * java.util.concurrent.ForkJoinTask} and its subclasses. These
+ * classes employ a work-stealing scheduler that attains high
+ * throughput for tasks conforming to restrictions that often hold in
+ * computation-intensive parallel processing.
+ *
* <h2>Queues</h2>
*
* The {@link java.util.concurrent.ConcurrentLinkedQueue} class
- * supplies an efficient scalable thread-safe non-blocking FIFO
- * queue.
+ * supplies an efficient scalable thread-safe non-blocking FIFO queue.
+ * The {@link java.util.concurrent.ConcurrentLinkedDeque} class is
+ * similar, but additionally supports the {@link java.util.Deque}
+ * interface.
*
* <p>Five implementations in {@code java.util.concurrent} support
* the extended {@link java.util.concurrent.BlockingQueue}
@@ -85,6 +90,12 @@
* for producer-consumer, messaging, parallel tasking, and
* related concurrent designs.
*
+ * <p>Extended interface {@link java.util.concurrent.TransferQueue},
+ * and implementation {@link java.util.concurrent.LinkedTransferQueue}
+ * introduce a synchronous {@code transfer} method (along with related
+ * features) in which a producer may optionally block awaiting its
+ * consumer.
+ *
* <p>The {@link java.util.concurrent.BlockingDeque} interface
* extends {@code BlockingQueue} to support both FIFO and LIFO
* (stack-based) operations.
@@ -111,7 +122,7 @@
*
* <h2>Synchronizers</h2>
*
- * Four classes aid common special-purpose synchronization idioms.
+ * Five classes aid common special-purpose synchronization idioms.
* <ul>
*
* <li>{@link java.util.concurrent.Semaphore} is a classic concurrency tool.
@@ -124,6 +135,10 @@
* multiway synchronization point useful in some styles of parallel
* programming.
*
+ * <li>A {@link java.util.concurrent.Phaser} provides
+ * a more flexible form of barrier that may be used to control phased
+ * computation among multiple threads.
+ *
* <li>An {@link java.util.concurrent.Exchanger} allows two threads to
* exchange objects at a rendezvous point, and is useful in several
* pipeline designs.
@@ -176,7 +191,7 @@
*
* <h2 id="MemoryVisibility">Memory Consistency Properties</h2>
*
- * <a href="http://java.sun.com/docs/books/jls/third_edition/html/memory.html">
+ * <a href="http://docs.oracle.com/javase/specs/jls/se7/html/jls-17.html#jls-17.4.5">
* Chapter 17 of the Java Language Specification</a> defines the
* <i>happens-before</i> relation on memory operations such as reads and
* writes of shared variables. The results of a write by one thread are
@@ -243,7 +258,8 @@
* in each thread <i>happen-before</i> those subsequent to the
* corresponding {@code exchange()} in another thread.
*
- * <li>Actions prior to calling {@code CyclicBarrier.await}
+ * <li>Actions prior to calling {@code CyclicBarrier.await} and
+ * {@code Phaser.awaitAdvance} (as well as its variants)
* <i>happen-before</i> actions performed by the barrier action, and
* actions performed by the barrier action <i>happen-before</i> actions
* subsequent to a successful return from the corresponding {@code await}