8231026: Miscellaneous changes imported from jsr166 CVS 2019-11
Reviewed-by: martin
--- a/src/java.base/share/classes/java/util/concurrent/CompletableFuture.java Fri Nov 01 09:04:04 2019 -0700
+++ b/src/java.base/share/classes/java/util/concurrent/CompletableFuture.java Fri Nov 01 09:07:59 2019 -0700
@@ -623,8 +623,8 @@
final CompletableFuture<V> tryFire(int mode) {
CompletableFuture<V> d; CompletableFuture<T> a;
Object r; Throwable x; Function<? super T,? extends V> f;
- if ((d = dep) == null || (f = fn) == null
- || (a = src) == null || (r = a.result) == null)
+ if ((a = src) == null || (r = a.result) == null
+ || (d = dep) == null || (f = fn) == null)
return null;
tryComplete: if (d.result == null) {
if (r instanceof AltResult) {
@@ -645,7 +645,7 @@
d.completeThrowable(ex);
}
}
- dep = null; src = null; fn = null;
+ src = null; dep = null; fn = null;
return d.postFire(a, mode);
}
}
@@ -695,8 +695,8 @@
final CompletableFuture<Void> tryFire(int mode) {
CompletableFuture<Void> d; CompletableFuture<T> a;
Object r; Throwable x; Consumer<? super T> f;
- if ((d = dep) == null || (f = fn) == null
- || (a = src) == null || (r = a.result) == null)
+ if ((a = src) == null || (r = a.result) == null
+ || (d = dep) == null || (f = fn) == null)
return null;
tryComplete: if (d.result == null) {
if (r instanceof AltResult) {
@@ -718,7 +718,7 @@
d.completeThrowable(ex);
}
}
- dep = null; src = null; fn = null;
+ src = null; dep = null; fn = null;
return d.postFire(a, mode);
}
}
@@ -769,8 +769,8 @@
final CompletableFuture<Void> tryFire(int mode) {
CompletableFuture<Void> d; CompletableFuture<T> a;
Object r; Throwable x; Runnable f;
- if ((d = dep) == null || (f = fn) == null
- || (a = src) == null || (r = a.result) == null)
+ if ((a = src) == null || (r = a.result) == null
+ || (d = dep) == null || (f = fn) == null)
return null;
if (d.result == null) {
if (r instanceof AltResult && (x = ((AltResult)r).ex) != null)
@@ -787,7 +787,7 @@
d.completeThrowable(ex);
}
}
- dep = null; src = null; fn = null;
+ src = null; dep = null; fn = null;
return d.postFire(a, mode);
}
}
@@ -832,11 +832,11 @@
final CompletableFuture<T> tryFire(int mode) {
CompletableFuture<T> d; CompletableFuture<T> a;
Object r; BiConsumer<? super T, ? super Throwable> f;
- if ((d = dep) == null || (f = fn) == null
- || (a = src) == null || (r = a.result) == null
+ if ((a = src) == null || (r = a.result) == null
+ || (d = dep) == null || (f = fn) == null
|| !d.uniWhenComplete(r, f, mode > 0 ? null : this))
return null;
- dep = null; src = null; fn = null;
+ src = null; dep = null; fn = null;
return d.postFire(a, mode);
}
}
@@ -902,11 +902,11 @@
final CompletableFuture<V> tryFire(int mode) {
CompletableFuture<V> d; CompletableFuture<T> a;
Object r; BiFunction<? super T, Throwable, ? extends V> f;
- if ((d = dep) == null || (f = fn) == null
- || (a = src) == null || (r = a.result) == null
+ if ((a = src) == null || (r = a.result) == null
+ || (d = dep) == null || (f = fn) == null
|| !d.uniHandle(r, f, mode > 0 ? null : this))
return null;
- dep = null; src = null; fn = null;
+ src = null; dep = null; fn = null;
return d.postFire(a, mode);
}
}
@@ -965,11 +965,11 @@
final CompletableFuture<T> tryFire(int mode) {
CompletableFuture<T> d; CompletableFuture<T> a;
Object r; Function<? super Throwable, ? extends T> f;
- if ((d = dep) == null || (f = fn) == null
- || (a = src) == null || (r = a.result) == null
+ if ((a = src) == null || (r = a.result) == null
+ || (d = dep) == null || (f = fn) == null
|| !d.uniExceptionally(r, f, mode > 0 ? null : this))
return null;
- dep = null; src = null; fn = null;
+ src = null; dep = null; fn = null;
return d.postFire(a, mode);
}
}
@@ -1024,8 +1024,8 @@
CompletableFuture<T> d; CompletableFuture<T> a;
Function<Throwable, ? extends CompletionStage<T>> f;
Object r; Throwable x;
- if ((d = dep) == null || (f = fn) == null
- || (a = src) == null || (r = a.result) == null)
+ if ((a = src) == null || (r = a.result) == null
+ || (d = dep) == null || (f = fn) == null)
return null;
if (d.result == null) {
if ((r instanceof AltResult) &&
@@ -1048,7 +1048,7 @@
else
d.internalComplete(r);
}
- dep = null; src = null; fn = null;
+ src = null; dep = null; fn = null;
return d.postFire(a, mode);
}
}
@@ -1086,8 +1086,8 @@
}
final CompletableFuture<U> tryFire(int mode) {
CompletableFuture<U> d; CompletableFuture<T> a; Object r;
- if ((d = dep) == null
- || (a = src) == null || (r = a.result) == null)
+ if ((a = src) == null || (r = a.result) == null
+ || (d = dep) == null)
return null;
if (d.result == null)
d.completeRelay(r);
@@ -1128,8 +1128,8 @@
CompletableFuture<V> d; CompletableFuture<T> a;
Function<? super T, ? extends CompletionStage<V>> f;
Object r; Throwable x;
- if ((d = dep) == null || (f = fn) == null
- || (a = src) == null || (r = a.result) == null)
+ if ((a = src) == null || (r = a.result) == null
+ || (d = dep) == null || (f = fn) == null)
return null;
tryComplete: if (d.result == null) {
if (r instanceof AltResult) {
@@ -1155,7 +1155,7 @@
d.completeThrowable(ex);
}
}
- dep = null; src = null; fn = null;
+ src = null; dep = null; fn = null;
return d.postFire(a, mode);
}
}
@@ -1270,12 +1270,12 @@
CompletableFuture<T> a;
CompletableFuture<U> b;
Object r, s; BiFunction<? super T,? super U,? extends V> f;
- if ((d = dep) == null || (f = fn) == null
- || (a = src) == null || (r = a.result) == null
+ if ( (a = src) == null || (r = a.result) == null
|| (b = snd) == null || (s = b.result) == null
+ || (d = dep) == null || (f = fn) == null
|| !d.biApply(r, s, f, mode > 0 ? null : this))
return null;
- dep = null; src = null; snd = null; fn = null;
+ src = null; snd = null; dep = null; fn = null;
return d.postFire(a, b, mode);
}
}
@@ -1345,12 +1345,12 @@
CompletableFuture<T> a;
CompletableFuture<U> b;
Object r, s; BiConsumer<? super T,? super U> f;
- if ((d = dep) == null || (f = fn) == null
- || (a = src) == null || (r = a.result) == null
+ if ( (a = src) == null || (r = a.result) == null
|| (b = snd) == null || (s = b.result) == null
+ || (d = dep) == null || (f = fn) == null
|| !d.biAccept(r, s, f, mode > 0 ? null : this))
return null;
- dep = null; src = null; snd = null; fn = null;
+ src = null; snd = null; dep = null; fn = null;
return d.postFire(a, b, mode);
}
}
@@ -1421,12 +1421,12 @@
CompletableFuture<T> a;
CompletableFuture<U> b;
Object r, s; Runnable f;
- if ((d = dep) == null || (f = fn) == null
- || (a = src) == null || (r = a.result) == null
+ if ( (a = src) == null || (r = a.result) == null
|| (b = snd) == null || (s = b.result) == null
+ || (d = dep) == null || (f = fn) == null
|| !d.biRun(r, s, f, mode > 0 ? null : this))
return null;
- dep = null; src = null; snd = null; fn = null;
+ src = null; snd = null; dep = null; fn = null;
return d.postFire(a, b, mode);
}
}
@@ -1482,9 +1482,9 @@
CompletableFuture<T> a;
CompletableFuture<U> b;
Object r, s, z; Throwable x;
- if ((d = dep) == null
- || (a = src) == null || (r = a.result) == null
- || (b = snd) == null || (s = b.result) == null)
+ if ( (a = src) == null || (r = a.result) == null
+ || (b = snd) == null || (s = b.result) == null
+ || (d = dep) == null)
return null;
if (d.result == null) {
if ((r instanceof AltResult
@@ -1557,13 +1557,11 @@
super(executor, dep, src, snd); this.fn = fn;
}
final CompletableFuture<V> tryFire(int mode) {
- CompletableFuture<V> d;
- CompletableFuture<T> a;
- CompletableFuture<U> b;
+ CompletableFuture<V> d; CompletableFuture<? extends T> a, b;
Object r; Throwable x; Function<? super T,? extends V> f;
- if ((d = dep) == null || (f = fn) == null
- || (a = src) == null || (b = snd) == null
- || ((r = a.result) == null && (r = b.result) == null))
+ if ((a = src) == null || (b = snd) == null
+ || ((r = a.result) == null && (r = b.result) == null)
+ || (d = dep) == null || (f = fn) == null)
return null;
tryComplete: if (d.result == null) {
try {
@@ -1582,7 +1580,7 @@
d.completeThrowable(ex);
}
}
- dep = null; src = null; snd = null; fn = null;
+ src = null; snd = null; dep = null; fn = null;
return d.postFire(a, b, mode);
}
}
@@ -1612,13 +1610,11 @@
super(executor, dep, src, snd); this.fn = fn;
}
final CompletableFuture<Void> tryFire(int mode) {
- CompletableFuture<Void> d;
- CompletableFuture<T> a;
- CompletableFuture<U> b;
+ CompletableFuture<Void> d; CompletableFuture<? extends T> a, b;
Object r; Throwable x; Consumer<? super T> f;
- if ((d = dep) == null || (f = fn) == null
- || (a = src) == null || (b = snd) == null
- || ((r = a.result) == null && (r = b.result) == null))
+ if ((a = src) == null || (b = snd) == null
+ || ((r = a.result) == null && (r = b.result) == null)
+ || (d = dep) == null || (f = fn) == null)
return null;
tryComplete: if (d.result == null) {
try {
@@ -1638,7 +1634,7 @@
d.completeThrowable(ex);
}
}
- dep = null; src = null; snd = null; fn = null;
+ src = null; snd = null; dep = null; fn = null;
return d.postFire(a, b, mode);
}
}
@@ -1668,13 +1664,11 @@
super(executor, dep, src, snd); this.fn = fn;
}
final CompletableFuture<Void> tryFire(int mode) {
- CompletableFuture<Void> d;
- CompletableFuture<T> a;
- CompletableFuture<U> b;
+ CompletableFuture<Void> d; CompletableFuture<?> a, b;
Object r; Throwable x; Runnable f;
- if ((d = dep) == null || (f = fn) == null
- || (a = src) == null || (b = snd) == null
- || ((r = a.result) == null && (r = b.result) == null))
+ if ((a = src) == null || (b = snd) == null
+ || ((r = a.result) == null && (r = b.result) == null)
+ || (d = dep) == null || (f = fn) == null)
return null;
if (d.result == null) {
try {
@@ -1691,7 +1685,7 @@
d.completeThrowable(ex);
}
}
- dep = null; src = null; snd = null; fn = null;
+ src = null; snd = null; dep = null; fn = null;
return d.postFire(a, b, mode);
}
}
@@ -1726,11 +1720,10 @@
CompletableFuture<Object> d; CompletableFuture<?> a;
CompletableFuture<?>[] as;
Object r;
- if ((d = dep) == null
- || (a = src) == null || (r = a.result) == null
- || (as = srcs) == null)
+ if ((a = src) == null || (r = a.result) == null
+ || (d = dep) == null || (as = srcs) == null)
return null;
- dep = null; src = null; srcs = null;
+ src = null; dep = null; srcs = null;
if (d.completeRelay(r)) {
for (CompletableFuture<?> b : as)
if (b != a)
--- a/test/jdk/java/util/concurrent/tck/StampedLockTest.java Fri Nov 01 09:04:04 2019 -0700
+++ b/test/jdk/java/util/concurrent/tck/StampedLockTest.java Fri Nov 01 09:07:59 2019 -0700
@@ -42,12 +42,17 @@
import java.util.ArrayList;
import java.util.List;
+import java.util.concurrent.Callable;
+import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Future;
+import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.StampedLock;
import java.util.function.BiConsumer;
+import java.util.function.Consumer;
import java.util.function.Function;
import junit.framework.Test;
@@ -102,56 +107,51 @@
}
List<Action> lockLockers(Lock lock) {
- List<Action> lockers = new ArrayList<>();
- lockers.add(() -> lock.lock());
- lockers.add(() -> lock.lockInterruptibly());
- lockers.add(() -> lock.tryLock());
- lockers.add(() -> lock.tryLock(Long.MIN_VALUE, DAYS));
- lockers.add(() -> lock.tryLock(0L, DAYS));
- lockers.add(() -> lock.tryLock(Long.MAX_VALUE, DAYS));
- return lockers;
+ return List.of(
+ () -> lock.lock(),
+ () -> lock.lockInterruptibly(),
+ () -> lock.tryLock(),
+ () -> lock.tryLock(Long.MIN_VALUE, DAYS),
+ () -> lock.tryLock(0L, DAYS),
+ () -> lock.tryLock(Long.MAX_VALUE, DAYS));
}
List<Function<StampedLock, Long>> readLockers() {
- List<Function<StampedLock, Long>> readLockers = new ArrayList<>();
- readLockers.add(sl -> sl.readLock());
- readLockers.add(sl -> sl.tryReadLock());
- readLockers.add(sl -> readLockInterruptiblyUninterrupted(sl));
- readLockers.add(sl -> tryReadLockUninterrupted(sl, Long.MIN_VALUE, DAYS));
- readLockers.add(sl -> tryReadLockUninterrupted(sl, 0L, DAYS));
- readLockers.add(sl -> sl.tryConvertToReadLock(sl.tryOptimisticRead()));
- return readLockers;
+ return List.of(
+ sl -> sl.readLock(),
+ sl -> sl.tryReadLock(),
+ sl -> readLockInterruptiblyUninterrupted(sl),
+ sl -> tryReadLockUninterrupted(sl, Long.MIN_VALUE, DAYS),
+ sl -> tryReadLockUninterrupted(sl, 0L, DAYS),
+ sl -> sl.tryConvertToReadLock(sl.tryOptimisticRead()));
}
List<BiConsumer<StampedLock, Long>> readUnlockers() {
- List<BiConsumer<StampedLock, Long>> readUnlockers = new ArrayList<>();
- readUnlockers.add((sl, stamp) -> sl.unlockRead(stamp));
- readUnlockers.add((sl, stamp) -> assertTrue(sl.tryUnlockRead()));
- readUnlockers.add((sl, stamp) -> sl.asReadLock().unlock());
- readUnlockers.add((sl, stamp) -> sl.unlock(stamp));
- readUnlockers.add((sl, stamp) -> assertValid(sl, sl.tryConvertToOptimisticRead(stamp)));
- return readUnlockers;
+ return List.of(
+ (sl, stamp) -> sl.unlockRead(stamp),
+ (sl, stamp) -> assertTrue(sl.tryUnlockRead()),
+ (sl, stamp) -> sl.asReadLock().unlock(),
+ (sl, stamp) -> sl.unlock(stamp),
+ (sl, stamp) -> assertValid(sl, sl.tryConvertToOptimisticRead(stamp)));
}
List<Function<StampedLock, Long>> writeLockers() {
- List<Function<StampedLock, Long>> writeLockers = new ArrayList<>();
- writeLockers.add(sl -> sl.writeLock());
- writeLockers.add(sl -> sl.tryWriteLock());
- writeLockers.add(sl -> writeLockInterruptiblyUninterrupted(sl));
- writeLockers.add(sl -> tryWriteLockUninterrupted(sl, Long.MIN_VALUE, DAYS));
- writeLockers.add(sl -> tryWriteLockUninterrupted(sl, 0L, DAYS));
- writeLockers.add(sl -> sl.tryConvertToWriteLock(sl.tryOptimisticRead()));
- return writeLockers;
+ return List.of(
+ sl -> sl.writeLock(),
+ sl -> sl.tryWriteLock(),
+ sl -> writeLockInterruptiblyUninterrupted(sl),
+ sl -> tryWriteLockUninterrupted(sl, Long.MIN_VALUE, DAYS),
+ sl -> tryWriteLockUninterrupted(sl, 0L, DAYS),
+ sl -> sl.tryConvertToWriteLock(sl.tryOptimisticRead()));
}
List<BiConsumer<StampedLock, Long>> writeUnlockers() {
- List<BiConsumer<StampedLock, Long>> writeUnlockers = new ArrayList<>();
- writeUnlockers.add((sl, stamp) -> sl.unlockWrite(stamp));
- writeUnlockers.add((sl, stamp) -> assertTrue(sl.tryUnlockWrite()));
- writeUnlockers.add((sl, stamp) -> sl.asWriteLock().unlock());
- writeUnlockers.add((sl, stamp) -> sl.unlock(stamp));
- writeUnlockers.add((sl, stamp) -> assertValid(sl, sl.tryConvertToOptimisticRead(stamp)));
- return writeUnlockers;
+ return List.of(
+ (sl, stamp) -> sl.unlockWrite(stamp),
+ (sl, stamp) -> assertTrue(sl.tryUnlockWrite()),
+ (sl, stamp) -> sl.asWriteLock().unlock(),
+ (sl, stamp) -> sl.unlock(stamp),
+ (sl, stamp) -> assertValid(sl, sl.tryConvertToOptimisticRead(stamp)));
}
/**
@@ -1413,4 +1413,113 @@
}
}
+ /**
+ * Multiple threads repeatedly contend for the same lock.
+ */
+ public void testConcurrentAccess() throws Exception {
+ final StampedLock sl = new StampedLock();
+ final Lock wl = sl.asWriteLock();
+ final Lock rl = sl.asReadLock();
+ final long testDurationMillis = expensiveTests ? 1000 : 2;
+ final int nTasks = ThreadLocalRandom.current().nextInt(1, 10);
+ final AtomicBoolean done = new AtomicBoolean(false);
+ final List<CompletableFuture> futures = new ArrayList<>();
+ final List<Callable<Long>> stampedWriteLockers = List.of(
+ () -> sl.writeLock(),
+ () -> writeLockInterruptiblyUninterrupted(sl),
+ () -> tryWriteLockUninterrupted(sl, LONG_DELAY_MS, MILLISECONDS),
+ () -> {
+ long stamp;
+ do { stamp = sl.tryConvertToWriteLock(sl.tryOptimisticRead()); }
+ while (stamp == 0L);
+ return stamp;
+ },
+ () -> {
+ long stamp;
+ do { stamp = sl.tryWriteLock(); } while (stamp == 0L);
+ return stamp;
+ },
+ () -> {
+ long stamp;
+ do { stamp = sl.tryWriteLock(0L, DAYS); } while (stamp == 0L);
+ return stamp;
+ });
+ final List<Callable<Long>> stampedReadLockers = List.of(
+ () -> sl.readLock(),
+ () -> readLockInterruptiblyUninterrupted(sl),
+ () -> tryReadLockUninterrupted(sl, LONG_DELAY_MS, MILLISECONDS),
+ () -> {
+ long stamp;
+ do { stamp = sl.tryConvertToReadLock(sl.tryOptimisticRead()); }
+ while (stamp == 0L);
+ return stamp;
+ },
+ () -> {
+ long stamp;
+ do { stamp = sl.tryReadLock(); } while (stamp == 0L);
+ return stamp;
+ },
+ () -> {
+ long stamp;
+ do { stamp = sl.tryReadLock(0L, DAYS); } while (stamp == 0L);
+ return stamp;
+ });
+ final List<Consumer<Long>> stampedWriteUnlockers = List.of(
+ stamp -> sl.unlockWrite(stamp),
+ stamp -> sl.unlock(stamp),
+ stamp -> assertTrue(sl.tryUnlockWrite()),
+ stamp -> wl.unlock(),
+ stamp -> sl.tryConvertToOptimisticRead(stamp));
+ final List<Consumer<Long>> stampedReadUnlockers = List.of(
+ stamp -> sl.unlockRead(stamp),
+ stamp -> sl.unlock(stamp),
+ stamp -> assertTrue(sl.tryUnlockRead()),
+ stamp -> rl.unlock(),
+ stamp -> sl.tryConvertToOptimisticRead(stamp));
+ final Action writer = () -> {
+ // repeatedly acquires write lock
+ var locker = chooseRandomly(stampedWriteLockers);
+ var unlocker = chooseRandomly(stampedWriteUnlockers);
+ while (!done.getAcquire()) {
+ long stamp = locker.call();
+ try {
+ assertTrue(isWriteLockStamp(stamp));
+ assertTrue(sl.isWriteLocked());
+ assertFalse(isReadLockStamp(stamp));
+ assertFalse(sl.isReadLocked());
+ assertEquals(0, sl.getReadLockCount());
+ assertTrue(sl.validate(stamp));
+ } finally {
+ unlocker.accept(stamp);
+ }
+ }
+ };
+ final Action reader = () -> {
+ // repeatedly acquires read lock
+ var locker = chooseRandomly(stampedReadLockers);
+ var unlocker = chooseRandomly(stampedReadUnlockers);
+ while (!done.getAcquire()) {
+ long stamp = locker.call();
+ try {
+ assertFalse(isWriteLockStamp(stamp));
+ assertFalse(sl.isWriteLocked());
+ assertTrue(isReadLockStamp(stamp));
+ assertTrue(sl.isReadLocked());
+ assertTrue(sl.getReadLockCount() > 0);
+ assertTrue(sl.validate(stamp));
+ } finally {
+ unlocker.accept(stamp);
+ }
+ }
+ };
+ for (int i = nTasks; i--> 0; ) {
+ Action task = chooseRandomly(writer, reader);
+ futures.add(CompletableFuture.runAsync(checkedRunnable(task)));
+ }
+ Thread.sleep(testDurationMillis);
+ done.setRelease(true);
+ for (var future : futures)
+ checkTimedGet(future, null);
+ }
+
}