8231026: Miscellaneous changes imported from jsr166 CVS 2019-11

Reviewed-by: martin
This commit is contained in:
Doug Lea 2019-11-01 09:07:59 -07:00
parent dc7d30d08e
commit f29d1d172b
2 changed files with 203 additions and 101 deletions

View File

@ -623,8 +623,8 @@ public class CompletableFuture<T> implements Future<T>, CompletionStage<T> {
final CompletableFuture<V> tryFire(int mode) { final CompletableFuture<V> tryFire(int mode) {
CompletableFuture<V> d; CompletableFuture<T> a; CompletableFuture<V> d; CompletableFuture<T> a;
Object r; Throwable x; Function<? super T,? extends V> f; Object r; Throwable x; Function<? super T,? extends V> f;
if ((d = dep) == null || (f = fn) == null if ((a = src) == null || (r = a.result) == null
|| (a = src) == null || (r = a.result) == null) || (d = dep) == null || (f = fn) == null)
return null; return null;
tryComplete: if (d.result == null) { tryComplete: if (d.result == null) {
if (r instanceof AltResult) { if (r instanceof AltResult) {
@ -645,7 +645,7 @@ public class CompletableFuture<T> implements Future<T>, CompletionStage<T> {
d.completeThrowable(ex); d.completeThrowable(ex);
} }
} }
dep = null; src = null; fn = null; src = null; dep = null; fn = null;
return d.postFire(a, mode); return d.postFire(a, mode);
} }
} }
@ -695,8 +695,8 @@ public class CompletableFuture<T> implements Future<T>, CompletionStage<T> {
final CompletableFuture<Void> tryFire(int mode) { final CompletableFuture<Void> tryFire(int mode) {
CompletableFuture<Void> d; CompletableFuture<T> a; CompletableFuture<Void> d; CompletableFuture<T> a;
Object r; Throwable x; Consumer<? super T> f; Object r; Throwable x; Consumer<? super T> f;
if ((d = dep) == null || (f = fn) == null if ((a = src) == null || (r = a.result) == null
|| (a = src) == null || (r = a.result) == null) || (d = dep) == null || (f = fn) == null)
return null; return null;
tryComplete: if (d.result == null) { tryComplete: if (d.result == null) {
if (r instanceof AltResult) { if (r instanceof AltResult) {
@ -718,7 +718,7 @@ public class CompletableFuture<T> implements Future<T>, CompletionStage<T> {
d.completeThrowable(ex); d.completeThrowable(ex);
} }
} }
dep = null; src = null; fn = null; src = null; dep = null; fn = null;
return d.postFire(a, mode); return d.postFire(a, mode);
} }
} }
@ -769,8 +769,8 @@ public class CompletableFuture<T> implements Future<T>, CompletionStage<T> {
final CompletableFuture<Void> tryFire(int mode) { final CompletableFuture<Void> tryFire(int mode) {
CompletableFuture<Void> d; CompletableFuture<T> a; CompletableFuture<Void> d; CompletableFuture<T> a;
Object r; Throwable x; Runnable f; Object r; Throwable x; Runnable f;
if ((d = dep) == null || (f = fn) == null if ((a = src) == null || (r = a.result) == null
|| (a = src) == null || (r = a.result) == null) || (d = dep) == null || (f = fn) == null)
return null; return null;
if (d.result == null) { if (d.result == null) {
if (r instanceof AltResult && (x = ((AltResult)r).ex) != null) if (r instanceof AltResult && (x = ((AltResult)r).ex) != null)
@ -787,7 +787,7 @@ public class CompletableFuture<T> implements Future<T>, CompletionStage<T> {
d.completeThrowable(ex); d.completeThrowable(ex);
} }
} }
dep = null; src = null; fn = null; src = null; dep = null; fn = null;
return d.postFire(a, mode); return d.postFire(a, mode);
} }
} }
@ -832,11 +832,11 @@ public class CompletableFuture<T> implements Future<T>, CompletionStage<T> {
final CompletableFuture<T> tryFire(int mode) { final CompletableFuture<T> tryFire(int mode) {
CompletableFuture<T> d; CompletableFuture<T> a; CompletableFuture<T> d; CompletableFuture<T> a;
Object r; BiConsumer<? super T, ? super Throwable> f; Object r; BiConsumer<? super T, ? super Throwable> f;
if ((d = dep) == null || (f = fn) == null if ((a = src) == null || (r = a.result) == null
|| (a = src) == null || (r = a.result) == null || (d = dep) == null || (f = fn) == null
|| !d.uniWhenComplete(r, f, mode > 0 ? null : this)) || !d.uniWhenComplete(r, f, mode > 0 ? null : this))
return null; return null;
dep = null; src = null; fn = null; src = null; dep = null; fn = null;
return d.postFire(a, mode); return d.postFire(a, mode);
} }
} }
@ -902,11 +902,11 @@ public class CompletableFuture<T> implements Future<T>, CompletionStage<T> {
final CompletableFuture<V> tryFire(int mode) { final CompletableFuture<V> tryFire(int mode) {
CompletableFuture<V> d; CompletableFuture<T> a; CompletableFuture<V> d; CompletableFuture<T> a;
Object r; BiFunction<? super T, Throwable, ? extends V> f; Object r; BiFunction<? super T, Throwable, ? extends V> f;
if ((d = dep) == null || (f = fn) == null if ((a = src) == null || (r = a.result) == null
|| (a = src) == null || (r = a.result) == null || (d = dep) == null || (f = fn) == null
|| !d.uniHandle(r, f, mode > 0 ? null : this)) || !d.uniHandle(r, f, mode > 0 ? null : this))
return null; return null;
dep = null; src = null; fn = null; src = null; dep = null; fn = null;
return d.postFire(a, mode); return d.postFire(a, mode);
} }
} }
@ -965,11 +965,11 @@ public class CompletableFuture<T> implements Future<T>, CompletionStage<T> {
final CompletableFuture<T> tryFire(int mode) { final CompletableFuture<T> tryFire(int mode) {
CompletableFuture<T> d; CompletableFuture<T> a; CompletableFuture<T> d; CompletableFuture<T> a;
Object r; Function<? super Throwable, ? extends T> f; Object r; Function<? super Throwable, ? extends T> f;
if ((d = dep) == null || (f = fn) == null if ((a = src) == null || (r = a.result) == null
|| (a = src) == null || (r = a.result) == null || (d = dep) == null || (f = fn) == null
|| !d.uniExceptionally(r, f, mode > 0 ? null : this)) || !d.uniExceptionally(r, f, mode > 0 ? null : this))
return null; return null;
dep = null; src = null; fn = null; src = null; dep = null; fn = null;
return d.postFire(a, mode); return d.postFire(a, mode);
} }
} }
@ -1024,8 +1024,8 @@ public class CompletableFuture<T> implements Future<T>, CompletionStage<T> {
CompletableFuture<T> d; CompletableFuture<T> a; CompletableFuture<T> d; CompletableFuture<T> a;
Function<Throwable, ? extends CompletionStage<T>> f; Function<Throwable, ? extends CompletionStage<T>> f;
Object r; Throwable x; Object r; Throwable x;
if ((d = dep) == null || (f = fn) == null if ((a = src) == null || (r = a.result) == null
|| (a = src) == null || (r = a.result) == null) || (d = dep) == null || (f = fn) == null)
return null; return null;
if (d.result == null) { if (d.result == null) {
if ((r instanceof AltResult) && if ((r instanceof AltResult) &&
@ -1048,7 +1048,7 @@ public class CompletableFuture<T> implements Future<T>, CompletionStage<T> {
else else
d.internalComplete(r); d.internalComplete(r);
} }
dep = null; src = null; fn = null; src = null; dep = null; fn = null;
return d.postFire(a, mode); return d.postFire(a, mode);
} }
} }
@ -1086,8 +1086,8 @@ public class CompletableFuture<T> implements Future<T>, CompletionStage<T> {
} }
final CompletableFuture<U> tryFire(int mode) { final CompletableFuture<U> tryFire(int mode) {
CompletableFuture<U> d; CompletableFuture<T> a; Object r; CompletableFuture<U> d; CompletableFuture<T> a; Object r;
if ((d = dep) == null if ((a = src) == null || (r = a.result) == null
|| (a = src) == null || (r = a.result) == null) || (d = dep) == null)
return null; return null;
if (d.result == null) if (d.result == null)
d.completeRelay(r); d.completeRelay(r);
@ -1128,8 +1128,8 @@ public class CompletableFuture<T> implements Future<T>, CompletionStage<T> {
CompletableFuture<V> d; CompletableFuture<T> a; CompletableFuture<V> d; CompletableFuture<T> a;
Function<? super T, ? extends CompletionStage<V>> f; Function<? super T, ? extends CompletionStage<V>> f;
Object r; Throwable x; Object r; Throwable x;
if ((d = dep) == null || (f = fn) == null if ((a = src) == null || (r = a.result) == null
|| (a = src) == null || (r = a.result) == null) || (d = dep) == null || (f = fn) == null)
return null; return null;
tryComplete: if (d.result == null) { tryComplete: if (d.result == null) {
if (r instanceof AltResult) { if (r instanceof AltResult) {
@ -1155,7 +1155,7 @@ public class CompletableFuture<T> implements Future<T>, CompletionStage<T> {
d.completeThrowable(ex); d.completeThrowable(ex);
} }
} }
dep = null; src = null; fn = null; src = null; dep = null; fn = null;
return d.postFire(a, mode); return d.postFire(a, mode);
} }
} }
@ -1270,12 +1270,12 @@ public class CompletableFuture<T> implements Future<T>, CompletionStage<T> {
CompletableFuture<T> a; CompletableFuture<T> a;
CompletableFuture<U> b; CompletableFuture<U> b;
Object r, s; BiFunction<? super T,? super U,? extends V> f; Object r, s; BiFunction<? super T,? super U,? extends V> f;
if ((d = dep) == null || (f = fn) == null if ( (a = src) == null || (r = a.result) == null
|| (a = src) == null || (r = a.result) == null
|| (b = snd) == null || (s = b.result) == null || (b = snd) == null || (s = b.result) == null
|| (d = dep) == null || (f = fn) == null
|| !d.biApply(r, s, f, mode > 0 ? null : this)) || !d.biApply(r, s, f, mode > 0 ? null : this))
return null; return null;
dep = null; src = null; snd = null; fn = null; src = null; snd = null; dep = null; fn = null;
return d.postFire(a, b, mode); return d.postFire(a, b, mode);
} }
} }
@ -1345,12 +1345,12 @@ public class CompletableFuture<T> implements Future<T>, CompletionStage<T> {
CompletableFuture<T> a; CompletableFuture<T> a;
CompletableFuture<U> b; CompletableFuture<U> b;
Object r, s; BiConsumer<? super T,? super U> f; Object r, s; BiConsumer<? super T,? super U> f;
if ((d = dep) == null || (f = fn) == null if ( (a = src) == null || (r = a.result) == null
|| (a = src) == null || (r = a.result) == null
|| (b = snd) == null || (s = b.result) == null || (b = snd) == null || (s = b.result) == null
|| (d = dep) == null || (f = fn) == null
|| !d.biAccept(r, s, f, mode > 0 ? null : this)) || !d.biAccept(r, s, f, mode > 0 ? null : this))
return null; return null;
dep = null; src = null; snd = null; fn = null; src = null; snd = null; dep = null; fn = null;
return d.postFire(a, b, mode); return d.postFire(a, b, mode);
} }
} }
@ -1421,12 +1421,12 @@ public class CompletableFuture<T> implements Future<T>, CompletionStage<T> {
CompletableFuture<T> a; CompletableFuture<T> a;
CompletableFuture<U> b; CompletableFuture<U> b;
Object r, s; Runnable f; Object r, s; Runnable f;
if ((d = dep) == null || (f = fn) == null if ( (a = src) == null || (r = a.result) == null
|| (a = src) == null || (r = a.result) == null
|| (b = snd) == null || (s = b.result) == null || (b = snd) == null || (s = b.result) == null
|| (d = dep) == null || (f = fn) == null
|| !d.biRun(r, s, f, mode > 0 ? null : this)) || !d.biRun(r, s, f, mode > 0 ? null : this))
return null; return null;
dep = null; src = null; snd = null; fn = null; src = null; snd = null; dep = null; fn = null;
return d.postFire(a, b, mode); return d.postFire(a, b, mode);
} }
} }
@ -1482,9 +1482,9 @@ public class CompletableFuture<T> implements Future<T>, CompletionStage<T> {
CompletableFuture<T> a; CompletableFuture<T> a;
CompletableFuture<U> b; CompletableFuture<U> b;
Object r, s, z; Throwable x; Object r, s, z; Throwable x;
if ((d = dep) == null if ( (a = src) == null || (r = a.result) == null
|| (a = src) == null || (r = a.result) == null || (b = snd) == null || (s = b.result) == null
|| (b = snd) == null || (s = b.result) == null) || (d = dep) == null)
return null; return null;
if (d.result == null) { if (d.result == null) {
if ((r instanceof AltResult if ((r instanceof AltResult
@ -1557,13 +1557,11 @@ public class CompletableFuture<T> implements Future<T>, CompletionStage<T> {
super(executor, dep, src, snd); this.fn = fn; super(executor, dep, src, snd); this.fn = fn;
} }
final CompletableFuture<V> tryFire(int mode) { final CompletableFuture<V> tryFire(int mode) {
CompletableFuture<V> d; CompletableFuture<V> d; CompletableFuture<? extends T> a, b;
CompletableFuture<T> a;
CompletableFuture<U> b;
Object r; Throwable x; Function<? super T,? extends V> f; Object r; Throwable x; Function<? super T,? extends V> f;
if ((d = dep) == null || (f = fn) == null if ((a = src) == null || (b = snd) == null
|| (a = src) == null || (b = snd) == null || ((r = a.result) == null && (r = b.result) == null)
|| ((r = a.result) == null && (r = b.result) == null)) || (d = dep) == null || (f = fn) == null)
return null; return null;
tryComplete: if (d.result == null) { tryComplete: if (d.result == null) {
try { try {
@ -1582,7 +1580,7 @@ public class CompletableFuture<T> implements Future<T>, CompletionStage<T> {
d.completeThrowable(ex); 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); return d.postFire(a, b, mode);
} }
} }
@ -1612,13 +1610,11 @@ public class CompletableFuture<T> implements Future<T>, CompletionStage<T> {
super(executor, dep, src, snd); this.fn = fn; super(executor, dep, src, snd); this.fn = fn;
} }
final CompletableFuture<Void> tryFire(int mode) { final CompletableFuture<Void> tryFire(int mode) {
CompletableFuture<Void> d; CompletableFuture<Void> d; CompletableFuture<? extends T> a, b;
CompletableFuture<T> a;
CompletableFuture<U> b;
Object r; Throwable x; Consumer<? super T> f; Object r; Throwable x; Consumer<? super T> f;
if ((d = dep) == null || (f = fn) == null if ((a = src) == null || (b = snd) == null
|| (a = src) == null || (b = snd) == null || ((r = a.result) == null && (r = b.result) == null)
|| ((r = a.result) == null && (r = b.result) == null)) || (d = dep) == null || (f = fn) == null)
return null; return null;
tryComplete: if (d.result == null) { tryComplete: if (d.result == null) {
try { try {
@ -1638,7 +1634,7 @@ public class CompletableFuture<T> implements Future<T>, CompletionStage<T> {
d.completeThrowable(ex); 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); return d.postFire(a, b, mode);
} }
} }
@ -1668,13 +1664,11 @@ public class CompletableFuture<T> implements Future<T>, CompletionStage<T> {
super(executor, dep, src, snd); this.fn = fn; super(executor, dep, src, snd); this.fn = fn;
} }
final CompletableFuture<Void> tryFire(int mode) { final CompletableFuture<Void> tryFire(int mode) {
CompletableFuture<Void> d; CompletableFuture<Void> d; CompletableFuture<?> a, b;
CompletableFuture<T> a;
CompletableFuture<U> b;
Object r; Throwable x; Runnable f; Object r; Throwable x; Runnable f;
if ((d = dep) == null || (f = fn) == null if ((a = src) == null || (b = snd) == null
|| (a = src) == null || (b = snd) == null || ((r = a.result) == null && (r = b.result) == null)
|| ((r = a.result) == null && (r = b.result) == null)) || (d = dep) == null || (f = fn) == null)
return null; return null;
if (d.result == null) { if (d.result == null) {
try { try {
@ -1691,7 +1685,7 @@ public class CompletableFuture<T> implements Future<T>, CompletionStage<T> {
d.completeThrowable(ex); 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); return d.postFire(a, b, mode);
} }
} }
@ -1726,11 +1720,10 @@ public class CompletableFuture<T> implements Future<T>, CompletionStage<T> {
CompletableFuture<Object> d; CompletableFuture<?> a; CompletableFuture<Object> d; CompletableFuture<?> a;
CompletableFuture<?>[] as; CompletableFuture<?>[] as;
Object r; Object r;
if ((d = dep) == null if ((a = src) == null || (r = a.result) == null
|| (a = src) == null || (r = a.result) == null || (d = dep) == null || (as = srcs) == null)
|| (as = srcs) == null)
return null; return null;
dep = null; src = null; srcs = null; src = null; dep = null; srcs = null;
if (d.completeRelay(r)) { if (d.completeRelay(r)) {
for (CompletableFuture<?> b : as) for (CompletableFuture<?> b : as)
if (b != a) if (b != a)

View File

@ -42,12 +42,17 @@ import static java.util.concurrent.locks.StampedLock.isWriteLockStamp;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CountDownLatch; import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Future; import java.util.concurrent.Future;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.StampedLock; import java.util.concurrent.locks.StampedLock;
import java.util.function.BiConsumer; import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.function.Function; import java.util.function.Function;
import junit.framework.Test; import junit.framework.Test;
@ -102,56 +107,51 @@ public class StampedLockTest extends JSR166TestCase {
} }
List<Action> lockLockers(Lock lock) { List<Action> lockLockers(Lock lock) {
List<Action> lockers = new ArrayList<>(); return List.of(
lockers.add(() -> lock.lock()); () -> lock.lock(),
lockers.add(() -> lock.lockInterruptibly()); () -> lock.lockInterruptibly(),
lockers.add(() -> lock.tryLock()); () -> lock.tryLock(),
lockers.add(() -> lock.tryLock(Long.MIN_VALUE, DAYS)); () -> lock.tryLock(Long.MIN_VALUE, DAYS),
lockers.add(() -> lock.tryLock(0L, DAYS)); () -> lock.tryLock(0L, DAYS),
lockers.add(() -> lock.tryLock(Long.MAX_VALUE, DAYS)); () -> lock.tryLock(Long.MAX_VALUE, DAYS));
return lockers;
} }
List<Function<StampedLock, Long>> readLockers() { List<Function<StampedLock, Long>> readLockers() {
List<Function<StampedLock, Long>> readLockers = new ArrayList<>(); return List.of(
readLockers.add(sl -> sl.readLock()); sl -> sl.readLock(),
readLockers.add(sl -> sl.tryReadLock()); sl -> sl.tryReadLock(),
readLockers.add(sl -> readLockInterruptiblyUninterrupted(sl)); sl -> readLockInterruptiblyUninterrupted(sl),
readLockers.add(sl -> tryReadLockUninterrupted(sl, Long.MIN_VALUE, DAYS)); sl -> tryReadLockUninterrupted(sl, Long.MIN_VALUE, DAYS),
readLockers.add(sl -> tryReadLockUninterrupted(sl, 0L, DAYS)); sl -> tryReadLockUninterrupted(sl, 0L, DAYS),
readLockers.add(sl -> sl.tryConvertToReadLock(sl.tryOptimisticRead())); sl -> sl.tryConvertToReadLock(sl.tryOptimisticRead()));
return readLockers;
} }
List<BiConsumer<StampedLock, Long>> readUnlockers() { List<BiConsumer<StampedLock, Long>> readUnlockers() {
List<BiConsumer<StampedLock, Long>> readUnlockers = new ArrayList<>(); return List.of(
readUnlockers.add((sl, stamp) -> sl.unlockRead(stamp)); (sl, stamp) -> sl.unlockRead(stamp),
readUnlockers.add((sl, stamp) -> assertTrue(sl.tryUnlockRead())); (sl, stamp) -> assertTrue(sl.tryUnlockRead()),
readUnlockers.add((sl, stamp) -> sl.asReadLock().unlock()); (sl, stamp) -> sl.asReadLock().unlock(),
readUnlockers.add((sl, stamp) -> sl.unlock(stamp)); (sl, stamp) -> sl.unlock(stamp),
readUnlockers.add((sl, stamp) -> assertValid(sl, sl.tryConvertToOptimisticRead(stamp))); (sl, stamp) -> assertValid(sl, sl.tryConvertToOptimisticRead(stamp)));
return readUnlockers;
} }
List<Function<StampedLock, Long>> writeLockers() { List<Function<StampedLock, Long>> writeLockers() {
List<Function<StampedLock, Long>> writeLockers = new ArrayList<>(); return List.of(
writeLockers.add(sl -> sl.writeLock()); sl -> sl.writeLock(),
writeLockers.add(sl -> sl.tryWriteLock()); sl -> sl.tryWriteLock(),
writeLockers.add(sl -> writeLockInterruptiblyUninterrupted(sl)); sl -> writeLockInterruptiblyUninterrupted(sl),
writeLockers.add(sl -> tryWriteLockUninterrupted(sl, Long.MIN_VALUE, DAYS)); sl -> tryWriteLockUninterrupted(sl, Long.MIN_VALUE, DAYS),
writeLockers.add(sl -> tryWriteLockUninterrupted(sl, 0L, DAYS)); sl -> tryWriteLockUninterrupted(sl, 0L, DAYS),
writeLockers.add(sl -> sl.tryConvertToWriteLock(sl.tryOptimisticRead())); sl -> sl.tryConvertToWriteLock(sl.tryOptimisticRead()));
return writeLockers;
} }
List<BiConsumer<StampedLock, Long>> writeUnlockers() { List<BiConsumer<StampedLock, Long>> writeUnlockers() {
List<BiConsumer<StampedLock, Long>> writeUnlockers = new ArrayList<>(); return List.of(
writeUnlockers.add((sl, stamp) -> sl.unlockWrite(stamp)); (sl, stamp) -> sl.unlockWrite(stamp),
writeUnlockers.add((sl, stamp) -> assertTrue(sl.tryUnlockWrite())); (sl, stamp) -> assertTrue(sl.tryUnlockWrite()),
writeUnlockers.add((sl, stamp) -> sl.asWriteLock().unlock()); (sl, stamp) -> sl.asWriteLock().unlock(),
writeUnlockers.add((sl, stamp) -> sl.unlock(stamp)); (sl, stamp) -> sl.unlock(stamp),
writeUnlockers.add((sl, stamp) -> assertValid(sl, sl.tryConvertToOptimisticRead(stamp))); (sl, stamp) -> assertValid(sl, sl.tryConvertToOptimisticRead(stamp)));
return writeUnlockers;
} }
/** /**
@ -1413,4 +1413,113 @@ public class StampedLockTest extends JSR166TestCase {
} }
} }
/**
* 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);
}
} }