changeset 57296:ec954ef6caf1

8231026: Miscellaneous changes imported from jsr166 CVS 2019-11 Reviewed-by: martin
author dl
date Fri, 01 Nov 2019 09:07:59 -0700
parents 35bac2745d04
children b95bead30957
files src/java.base/share/classes/java/util/concurrent/CompletableFuture.java test/jdk/java/util/concurrent/tck/StampedLockTest.java
diffstat 2 files changed, 203 insertions(+), 101 deletions(-) [+]
line wrap: on
line diff
--- 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);
+    }
+
 }