8231026: Miscellaneous changes imported from jsr166 CVS 2019-11
Reviewed-by: martin
This commit is contained in:
parent
dc7d30d08e
commit
f29d1d172b
@ -623,8 +623,8 @@ public class CompletableFuture<T> implements Future<T>, CompletionStage<T> {
|
||||
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 @@ public class CompletableFuture<T> implements Future<T>, CompletionStage<T> {
|
||||
d.completeThrowable(ex);
|
||||
}
|
||||
}
|
||||
dep = null; src = null; fn = null;
|
||||
src = null; dep = null; fn = null;
|
||||
return d.postFire(a, mode);
|
||||
}
|
||||
}
|
||||
@ -695,8 +695,8 @@ public class CompletableFuture<T> implements Future<T>, CompletionStage<T> {
|
||||
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 @@ public class CompletableFuture<T> implements Future<T>, CompletionStage<T> {
|
||||
d.completeThrowable(ex);
|
||||
}
|
||||
}
|
||||
dep = null; src = null; fn = null;
|
||||
src = null; dep = null; fn = null;
|
||||
return d.postFire(a, mode);
|
||||
}
|
||||
}
|
||||
@ -769,8 +769,8 @@ public class CompletableFuture<T> implements Future<T>, CompletionStage<T> {
|
||||
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 @@ public class CompletableFuture<T> implements Future<T>, CompletionStage<T> {
|
||||
d.completeThrowable(ex);
|
||||
}
|
||||
}
|
||||
dep = null; src = null; fn = null;
|
||||
src = null; dep = null; fn = null;
|
||||
return d.postFire(a, mode);
|
||||
}
|
||||
}
|
||||
@ -832,11 +832,11 @@ public class CompletableFuture<T> implements Future<T>, CompletionStage<T> {
|
||||
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 @@ public class CompletableFuture<T> implements Future<T>, CompletionStage<T> {
|
||||
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 @@ public class CompletableFuture<T> implements Future<T>, CompletionStage<T> {
|
||||
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 @@ public class CompletableFuture<T> implements Future<T>, CompletionStage<T> {
|
||||
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 @@ public class CompletableFuture<T> implements Future<T>, CompletionStage<T> {
|
||||
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 @@ public class CompletableFuture<T> implements Future<T>, CompletionStage<T> {
|
||||
}
|
||||
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 @@ public class CompletableFuture<T> implements Future<T>, CompletionStage<T> {
|
||||
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 @@ public class CompletableFuture<T> implements Future<T>, CompletionStage<T> {
|
||||
d.completeThrowable(ex);
|
||||
}
|
||||
}
|
||||
dep = null; src = null; fn = null;
|
||||
src = null; dep = null; fn = null;
|
||||
return d.postFire(a, mode);
|
||||
}
|
||||
}
|
||||
@ -1270,12 +1270,12 @@ public class CompletableFuture<T> implements Future<T>, CompletionStage<T> {
|
||||
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 @@ public class CompletableFuture<T> implements Future<T>, CompletionStage<T> {
|
||||
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 @@ public class CompletableFuture<T> implements Future<T>, CompletionStage<T> {
|
||||
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 @@ public class CompletableFuture<T> implements Future<T>, CompletionStage<T> {
|
||||
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 @@ public class CompletableFuture<T> implements Future<T>, CompletionStage<T> {
|
||||
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 @@ public class CompletableFuture<T> implements Future<T>, CompletionStage<T> {
|
||||
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 @@ public class CompletableFuture<T> implements Future<T>, CompletionStage<T> {
|
||||
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 @@ public class CompletableFuture<T> implements Future<T>, CompletionStage<T> {
|
||||
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 @@ public class CompletableFuture<T> implements Future<T>, CompletionStage<T> {
|
||||
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 @@ public class CompletableFuture<T> implements Future<T>, CompletionStage<T> {
|
||||
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 @@ public class CompletableFuture<T> implements Future<T>, CompletionStage<T> {
|
||||
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)
|
||||
|
@ -42,12 +42,17 @@ import static java.util.concurrent.locks.StampedLock.isWriteLockStamp;
|
||||
|
||||
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 @@ public class StampedLockTest extends JSR166TestCase {
|
||||
}
|
||||
|
||||
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 @@ 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);
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user