8215249: Miscellaneous changes imported from jsr166 CVS 2019-02
Reviewed-by: martin, chegar, dholmes
--- a/src/java.base/share/classes/java/util/concurrent/CyclicBarrier.java Fri Feb 15 11:18:01 2019 -0800
+++ b/src/java.base/share/classes/java/util/concurrent/CyclicBarrier.java Fri Feb 15 11:18:01 2019 -0800
@@ -98,12 +98,11 @@
* }
* }}</pre>
*
- * Here, each worker thread processes a row of the matrix then waits at the
- * barrier until all rows have been processed. When all rows are processed
- * the supplied {@link Runnable} barrier action is executed and merges the
- * rows. If the merger
- * determines that a solution has been found then {@code done()} will return
- * {@code true} and each worker will terminate.
+ * Here, each worker thread processes a row of the matrix, then waits at the
+ * barrier until all rows have been processed. When all rows are processed the
+ * supplied {@link Runnable} barrier action is executed and merges the rows.
+ * If the merger determines that a solution has been found then {@code done()}
+ * will return {@code true} and each worker will terminate.
*
* <p>If the barrier action does not rely on the parties being suspended when
* it is executed, then any of the threads in the party could execute that
@@ -132,6 +131,7 @@
* corresponding {@code await()} in other threads.
*
* @see CountDownLatch
+ * @see Phaser
*
* @author Doug Lea
* @since 1.5
@@ -214,18 +214,17 @@
int index = --count;
if (index == 0) { // tripped
- boolean ranAction = false;
- try {
- final Runnable command = barrierCommand;
- if (command != null)
+ Runnable command = barrierCommand;
+ if (command != null) {
+ try {
command.run();
- ranAction = true;
- nextGeneration();
- return 0;
- } finally {
- if (!ranAction)
+ } catch (Throwable ex) {
breakBarrier();
+ throw ex;
+ }
}
+ nextGeneration();
+ return 0;
}
// loop until tripped, broken, interrupted, or timed out
--- a/test/jdk/java/util/Collection/IteratorMicroBenchmark.java Fri Feb 15 11:18:01 2019 -0800
+++ b/test/jdk/java/util/Collection/IteratorMicroBenchmark.java Fri Feb 15 11:18:01 2019 -0800
@@ -69,8 +69,6 @@
* Be patient; this program runs for a very long time.
* For faster runs, restrict execution using command line args.
*
- * This is an interface based version of ArrayList/IteratorMicroBenchmark
- *
* @author Martin Buchholz
*/
public class IteratorMicroBenchmark {
@@ -115,7 +113,9 @@
CountDownLatch finalized = new CountDownLatch(1);
ReferenceQueue<Object> queue = new ReferenceQueue<>();
WeakReference<Object> ref = new WeakReference<>(
- new Object() { protected void finalize() { finalized.countDown(); }},
+ new Object() {
+ @SuppressWarnings("deprecation")
+ protected void finalize() { finalized.countDown(); }},
queue);
try {
for (int tries = 3; tries--> 0; ) {
@@ -267,16 +267,22 @@
});
}
- static List<Integer> makeSubList(List<Integer> list) {
+ String goodClassName(Object x) {
+ return goodClassName(x.getClass());
+ }
+
+ static List<Integer> makeSubList(
+ List<Integer> elements,
+ UnaryOperator<List<Integer>> copyConstructor) {
+ final ArrayList<Integer> padded = new ArrayList<>();
final ThreadLocalRandom rnd = ThreadLocalRandom.current();
- int size = list.size();
- if (size <= 2) return list.subList(0, size);
- List<Integer> subList = list.subList(rnd.nextInt(0, 2),
- size - rnd.nextInt(0, 2));
- List<Integer> copy = new ArrayList<>(list);
- subList.clear();
- subList.addAll(copy);
- return subList;
+ final int frontPorch = rnd.nextInt(3);
+ final int backPorch = rnd.nextInt(3);
+ for (int n = frontPorch; n--> 0; ) padded.add(rnd.nextInt());
+ padded.addAll(elements);
+ for (int n = backPorch; n--> 0; ) padded.add(rnd.nextInt());
+ return copyConstructor.apply(padded)
+ .subList(frontPorch, frontPorch + elements.size());
}
void run() throws Throwable {
@@ -297,22 +303,42 @@
abq.add(abq.remove());
}
- ArrayList<Job> jobs = Stream.<Collection<Integer>>of(
- al, ad, abq,
- makeSubList(new ArrayList<>(al)),
+ final Integer[] array = al.toArray(new Integer[0]);
+ final List<Integer> immutableSubList
+ = makeSubList(al, x -> List.of(x.toArray(new Integer[0])));
+
+ Stream<Collection<Integer>> collections = concatStreams(
+ Stream.of(
+ // Lists and their subLists
+ al,
+ makeSubList(al, ArrayList::new),
+ new Vector<>(al),
+ makeSubList(al, Vector::new),
new LinkedList<>(al),
- makeSubList(new LinkedList<>(al)),
+ makeSubList(al, LinkedList::new),
+ new CopyOnWriteArrayList<>(al),
+ makeSubList(al, CopyOnWriteArrayList::new),
+
+ ad,
new PriorityQueue<>(al),
- new Vector<>(al),
- makeSubList(new Vector<>(al)),
- new CopyOnWriteArrayList<>(al),
- makeSubList(new CopyOnWriteArrayList<>(al)),
new ConcurrentLinkedQueue<>(al),
new ConcurrentLinkedDeque<>(al),
+
+ // Blocking Queues
+ abq,
new LinkedBlockingQueue<>(al),
new LinkedBlockingDeque<>(al),
new LinkedTransferQueue<>(al),
- new PriorityBlockingQueue<>(al))
+ new PriorityBlockingQueue<>(al),
+
+ List.of(al.toArray(new Integer[0]))),
+
+ // avoid UnsupportedOperationException in jdk9 and jdk10
+ (goodClassName(immutableSubList).equals("RandomAccessSubList"))
+ ? Stream.empty()
+ : Stream.of(immutableSubList));
+
+ ArrayList<Job> jobs = collections
.flatMap(x -> jobs(x))
.filter(job ->
nameFilter == null || nameFilter.matcher(job.name()).find())
@@ -329,16 +355,29 @@
return Stream.of(streams).flatMap(s -> s);
}
+ boolean isMutable(Collection<Integer> x) {
+ return !(x.getClass().getName().contains("ImmutableCollections$"));
+ }
+
Stream<Job> jobs(Collection<Integer> x) {
+ final String klazz = goodClassName(x);
return concatStreams(
collectionJobs(x),
+ (isMutable(x))
+ ? mutableCollectionJobs(x)
+ : Stream.empty(),
+
(x instanceof Deque)
? dequeJobs((Deque<Integer>)x)
: Stream.empty(),
(x instanceof List)
? listJobs((List<Integer>)x)
+ : Stream.empty(),
+
+ (x instanceof List && isMutable(x))
+ ? mutableListJobs((List<Integer>)x)
: Stream.empty());
}
@@ -350,7 +389,7 @@
}
Stream<Job> collectionJobs(Collection<Integer> x) {
- final String klazz = goodClassName(x.getClass());
+ final String klazz = goodClassName(x);
return Stream.of(
new Job(klazz + " iterate for loop") {
public void work() throws Throwable {
@@ -381,14 +420,6 @@
sum[0] = 0;
x.spliterator().forEachRemaining(n -> sum[0] += n);
check.sum(sum[0]);}}},
- new Job(klazz + " removeIf") {
- public void work() throws Throwable {
- int[] sum = new int[1];
- for (int i = 0; i < iterations; i++) {
- sum[0] = 0;
- if (x.removeIf(n -> { sum[0] += n; return false; }))
- throw new AssertionError();
- check.sum(sum[0]);}}},
new Job(klazz + " contains") {
public void work() throws Throwable {
int[] sum = new int[1];
@@ -407,14 +438,6 @@
if (x.containsAll(sneakyAdderCollection))
throw new AssertionError();
check.sum(sum[0]);}}},
- new Job(klazz + " remove(Object)") {
- public void work() throws Throwable {
- int[] sum = new int[1];
- Object sneakyAdder = sneakyAdder(sum);
- for (int i = 0; i < iterations; i++) {
- sum[0] = 0;
- if (x.remove(sneakyAdder)) throw new AssertionError();
- check.sum(sum[0]);}}},
new Job(klazz + " forEach") {
public void work() throws Throwable {
int[] sum = new int[1];
@@ -498,8 +521,29 @@
check.sum(sum[0]);}}});
}
+ Stream<Job> mutableCollectionJobs(Collection<Integer> x) {
+ final String klazz = goodClassName(x);
+ return Stream.of(
+ new Job(klazz + " removeIf") {
+ public void work() throws Throwable {
+ int[] sum = new int[1];
+ for (int i = 0; i < iterations; i++) {
+ sum[0] = 0;
+ if (x.removeIf(n -> { sum[0] += n; return false; }))
+ throw new AssertionError();
+ check.sum(sum[0]);}}},
+ new Job(klazz + " remove(Object)") {
+ public void work() throws Throwable {
+ int[] sum = new int[1];
+ Object sneakyAdder = sneakyAdder(sum);
+ for (int i = 0; i < iterations; i++) {
+ sum[0] = 0;
+ if (x.remove(sneakyAdder)) throw new AssertionError();
+ check.sum(sum[0]);}}});
+ }
+
Stream<Job> dequeJobs(Deque<Integer> x) {
- String klazz = goodClassName(x.getClass());
+ final String klazz = goodClassName(x);
return Stream.of(
new Job(klazz + " descendingIterator() loop") {
public void work() throws Throwable {
@@ -519,7 +563,7 @@
}
Stream<Job> listJobs(List<Integer> x) {
- final String klazz = goodClassName(x.getClass());
+ final String klazz = goodClassName(x);
return Stream.of(
new Job(klazz + " listIterator forward loop") {
public void work() throws Throwable {
@@ -555,15 +599,6 @@
if (x.lastIndexOf(sneakyAdder) != -1)
throw new AssertionError();
check.sum(sum[0]);}}},
- new Job(klazz + " replaceAll") {
- public void work() throws Throwable {
- int[] sum = new int[1];
- UnaryOperator<Integer> sneakyAdder =
- x -> { sum[0] += x; return x; };
- for (int i = 0; i < iterations; i++) {
- sum[0] = 0;
- x.replaceAll(sneakyAdder);
- check.sum(sum[0]);}}},
new Job(klazz + " equals") {
public void work() throws Throwable {
ArrayList<Integer> copy = new ArrayList<>(x);
@@ -577,4 +612,18 @@
if (x.hashCode() != hashCode)
throw new AssertionError();}}});
}
+
+ Stream<Job> mutableListJobs(List<Integer> x) {
+ final String klazz = goodClassName(x);
+ return Stream.of(
+ new Job(klazz + " replaceAll") {
+ public void work() throws Throwable {
+ int[] sum = new int[1];
+ UnaryOperator<Integer> sneakyAdder =
+ x -> { sum[0] += x; return x; };
+ for (int i = 0; i < iterations; i++) {
+ sum[0] = 0;
+ x.replaceAll(sneakyAdder);
+ check.sum(sum[0]);}}});
+ }
}
--- a/test/jdk/java/util/Collection/RemoveMicroBenchmark.java Fri Feb 15 11:18:01 2019 -0800
+++ b/test/jdk/java/util/Collection/RemoveMicroBenchmark.java Fri Feb 15 11:18:01 2019 -0800
@@ -270,6 +270,10 @@
});
}
+ String goodClassName(Object x) {
+ return goodClassName(x.getClass());
+ }
+
static List<Integer> makeSubList(List<Integer> list) {
final ThreadLocalRandom rnd = ThreadLocalRandom.current();
int size = rnd.nextInt(4);
@@ -369,7 +373,7 @@
}
Stream<Job> collectionJobs(Collection<Integer> x) {
- final String klazz = goodClassName(x.getClass());
+ final String klazz = goodClassName(x);
return Stream.of(
new Job(klazz + " removeIf") {
public void work() throws Throwable {
@@ -422,7 +426,7 @@
}
Stream<Job> iteratorRemoveJobs(Collection<Integer> x) {
- final String klazz = goodClassName(x.getClass());
+ final String klazz = goodClassName(x);
return Stream.of(
new Job(klazz + " Iterator.remove") {
public void work() throws Throwable {
@@ -460,7 +464,7 @@
}
Stream<Job> queueJobs(Queue<Integer> x) {
- final String klazz = goodClassName(x.getClass());
+ final String klazz = goodClassName(x);
return Stream.of(
new Job(klazz + " poll()") {
public void work() throws Throwable {
@@ -474,7 +478,7 @@
}
Stream<Job> dequeJobs(Deque<Integer> x) {
- final String klazz = goodClassName(x.getClass());
+ final String klazz = goodClassName(x);
return Stream.of(
new Job(klazz + " descendingIterator().remove") {
public void work() throws Throwable {
@@ -509,7 +513,7 @@
}
Stream<Job> blockingQueueJobs(BlockingQueue<Integer> x) {
- final String klazz = goodClassName(x.getClass());
+ final String klazz = goodClassName(x);
return Stream.of(
new Job(klazz + " timed poll()") {
public void work() throws Throwable {
@@ -545,7 +549,7 @@
}
Stream<Job> blockingDequeJobs(BlockingDeque<Integer> x) {
- final String klazz = goodClassName(x.getClass());
+ final String klazz = goodClassName(x);
return Stream.of(
new Job(klazz + " timed pollFirst()") {
public void work() throws Throwable {
--- a/test/jdk/java/util/concurrent/tck/CyclicBarrierTest.java Fri Feb 15 11:18:01 2019 -0800
+++ b/test/jdk/java/util/concurrent/tck/CyclicBarrierTest.java Fri Feb 15 11:18:01 2019 -0800
@@ -38,6 +38,9 @@
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.CyclicBarrier;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
@@ -486,4 +489,34 @@
assertEquals(0, barrier.getNumberWaiting());
}
}
+
+ /**
+ * There can be more threads calling await() than parties, as long as each
+ * task only calls await once and the task count is a multiple of parties.
+ */
+ public void testMoreTasksThanParties() throws Exception {
+ final ThreadLocalRandom rnd = ThreadLocalRandom.current();
+ final int parties = rnd.nextInt(1, 5);
+ final int nTasks = rnd.nextInt(1, 5) * parties;
+ final AtomicInteger tripCount = new AtomicInteger(0);
+ final AtomicInteger awaitCount = new AtomicInteger(0);
+ final CyclicBarrier barrier =
+ new CyclicBarrier(parties, () -> tripCount.getAndIncrement());
+ final ExecutorService e = Executors.newFixedThreadPool(nTasks);
+ final Runnable awaiter = () -> {
+ try {
+ if (ThreadLocalRandom.current().nextBoolean())
+ barrier.await();
+ else
+ barrier.await(LONG_DELAY_MS, MILLISECONDS);
+ awaitCount.getAndIncrement();
+ } catch (Throwable fail) { threadUnexpectedException(fail); }};
+ try (PoolCleaner cleaner = cleaner(e)) {
+ for (int i = nTasks; i--> 0; )
+ e.execute(awaiter);
+ }
+ assertEquals(nTasks / parties, tripCount.get());
+ assertEquals(nTasks, awaitCount.get());
+ assertEquals(0, barrier.getNumberWaiting());
+ }
}