ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/test/tck/StampedLockTest.java
(Generate patch)

Comparing jsr166/src/test/tck/StampedLockTest.java (file contents):
Revision 1.39 by jsr166, Sun Sep 24 15:24:34 2017 UTC vs.
Revision 1.46 by jsr166, Wed Aug 12 16:15:28 2020 UTC

# Line 8 | Line 8
8   import static java.util.concurrent.TimeUnit.DAYS;
9   import static java.util.concurrent.TimeUnit.MILLISECONDS;
10  
11 + import static java.util.concurrent.locks.StampedLock.isLockStamp;
12 + import static java.util.concurrent.locks.StampedLock.isOptimisticReadStamp;
13 + import static java.util.concurrent.locks.StampedLock.isReadLockStamp;
14 + import static java.util.concurrent.locks.StampedLock.isWriteLockStamp;
15 +
16   import java.util.ArrayList;
17   import java.util.List;
18 + import java.util.concurrent.Callable;
19 + import java.util.concurrent.CompletableFuture;
20   import java.util.concurrent.CountDownLatch;
21   import java.util.concurrent.Future;
22 + import java.util.concurrent.ThreadLocalRandom;
23   import java.util.concurrent.TimeUnit;
24 + import java.util.concurrent.atomic.AtomicBoolean;
25   import java.util.concurrent.locks.Lock;
26   import java.util.concurrent.locks.StampedLock;
27   import java.util.function.BiConsumer;
28 + import java.util.function.Consumer;
29   import java.util.function.Function;
30  
31   import junit.framework.Test;
# Line 70 | Line 80 | public class StampedLockTest extends JSR
80      }
81  
82      List<Action> lockLockers(Lock lock) {
83 <        List<Action> lockers = new ArrayList<>();
84 <        lockers.add(() -> lock.lock());
85 <        lockers.add(() -> lock.lockInterruptibly());
86 <        lockers.add(() -> lock.tryLock());
87 <        lockers.add(() -> lock.tryLock(Long.MIN_VALUE, DAYS));
88 <        lockers.add(() -> lock.tryLock(0L, DAYS));
89 <        lockers.add(() -> lock.tryLock(Long.MAX_VALUE, DAYS));
80 <        return lockers;
83 >        return List.of(
84 >            () -> lock.lock(),
85 >            () -> lock.lockInterruptibly(),
86 >            () -> lock.tryLock(),
87 >            () -> lock.tryLock(Long.MIN_VALUE, DAYS),
88 >            () -> lock.tryLock(0L, DAYS),
89 >            () -> lock.tryLock(Long.MAX_VALUE, DAYS));
90      }
91  
92      List<Function<StampedLock, Long>> readLockers() {
93 <        List<Function<StampedLock, Long>> readLockers = new ArrayList<>();
94 <        readLockers.add(sl -> sl.readLock());
95 <        readLockers.add(sl -> sl.tryReadLock());
96 <        readLockers.add(sl -> readLockInterruptiblyUninterrupted(sl));
97 <        readLockers.add(sl -> tryReadLockUninterrupted(sl, Long.MIN_VALUE, DAYS));
98 <        readLockers.add(sl -> tryReadLockUninterrupted(sl, 0L, DAYS));
99 <        readLockers.add(sl -> sl.tryConvertToReadLock(sl.tryOptimisticRead()));
91 <        return readLockers;
93 >        return List.of(
94 >            sl -> sl.readLock(),
95 >            sl -> sl.tryReadLock(),
96 >            sl -> readLockInterruptiblyUninterrupted(sl),
97 >            sl -> tryReadLockUninterrupted(sl, Long.MIN_VALUE, DAYS),
98 >            sl -> tryReadLockUninterrupted(sl, 0L, DAYS),
99 >            sl -> sl.tryConvertToReadLock(sl.tryOptimisticRead()));
100      }
101  
102      List<BiConsumer<StampedLock, Long>> readUnlockers() {
103 <        List<BiConsumer<StampedLock, Long>> readUnlockers = new ArrayList<>();
104 <        readUnlockers.add((sl, stamp) -> sl.unlockRead(stamp));
105 <        readUnlockers.add((sl, stamp) -> assertTrue(sl.tryUnlockRead()));
106 <        readUnlockers.add((sl, stamp) -> sl.asReadLock().unlock());
107 <        readUnlockers.add((sl, stamp) -> sl.unlock(stamp));
108 <        readUnlockers.add((sl, stamp) -> assertValid(sl, sl.tryConvertToOptimisticRead(stamp)));
101 <        return readUnlockers;
103 >        return List.of(
104 >            (sl, stamp) -> sl.unlockRead(stamp),
105 >            (sl, stamp) -> assertTrue(sl.tryUnlockRead()),
106 >            (sl, stamp) -> sl.asReadLock().unlock(),
107 >            (sl, stamp) -> sl.unlock(stamp),
108 >            (sl, stamp) -> assertValid(sl, sl.tryConvertToOptimisticRead(stamp)));
109      }
110  
111      List<Function<StampedLock, Long>> writeLockers() {
112 <        List<Function<StampedLock, Long>> writeLockers = new ArrayList<>();
113 <        writeLockers.add(sl -> sl.writeLock());
114 <        writeLockers.add(sl -> sl.tryWriteLock());
115 <        writeLockers.add(sl -> writeLockInterruptiblyUninterrupted(sl));
116 <        writeLockers.add(sl -> tryWriteLockUninterrupted(sl, Long.MIN_VALUE, DAYS));
117 <        writeLockers.add(sl -> tryWriteLockUninterrupted(sl, 0L, DAYS));
118 <        writeLockers.add(sl -> sl.tryConvertToWriteLock(sl.tryOptimisticRead()));
112 <        return writeLockers;
112 >        return List.of(
113 >            sl -> sl.writeLock(),
114 >            sl -> sl.tryWriteLock(),
115 >            sl -> writeLockInterruptiblyUninterrupted(sl),
116 >            sl -> tryWriteLockUninterrupted(sl, Long.MIN_VALUE, DAYS),
117 >            sl -> tryWriteLockUninterrupted(sl, 0L, DAYS),
118 >            sl -> sl.tryConvertToWriteLock(sl.tryOptimisticRead()));
119      }
120  
121      List<BiConsumer<StampedLock, Long>> writeUnlockers() {
122 <        List<BiConsumer<StampedLock, Long>> writeUnlockers = new ArrayList<>();
123 <        writeUnlockers.add((sl, stamp) -> sl.unlockWrite(stamp));
124 <        writeUnlockers.add((sl, stamp) -> assertTrue(sl.tryUnlockWrite()));
125 <        writeUnlockers.add((sl, stamp) -> sl.asWriteLock().unlock());
126 <        writeUnlockers.add((sl, stamp) -> sl.unlock(stamp));
127 <        writeUnlockers.add((sl, stamp) -> assertValid(sl, sl.tryConvertToOptimisticRead(stamp)));
122 <        return writeUnlockers;
122 >        return List.of(
123 >            (sl, stamp) -> sl.unlockWrite(stamp),
124 >            (sl, stamp) -> assertTrue(sl.tryUnlockWrite()),
125 >            (sl, stamp) -> sl.asWriteLock().unlock(),
126 >            (sl, stamp) -> sl.unlock(stamp),
127 >            (sl, stamp) -> assertValid(sl, sl.tryConvertToOptimisticRead(stamp)));
128      }
129  
130      /**
# Line 338 | Line 343 | public class StampedLockTest extends JSR
343       */
344      public void testInterruptibleOperationsThrowInterruptedExceptionWriteLockedInterrupted() {
345          final StampedLock lock = new StampedLock();
346 <        long s = lock.writeLock();
346 >        long stamp = lock.writeLock();
347  
348          Action[] interruptibleLockBlockingActions = {
349              () -> lock.writeLockInterruptibly(),
# Line 353 | Line 358 | public class StampedLockTest extends JSR
358          shuffle(interruptibleLockBlockingActions);
359  
360          assertThrowInterruptedExceptionWhenInterrupted(interruptibleLockBlockingActions);
361 +
362 +        releaseWriteLock(lock, stamp);
363      }
364  
365      /**
# Line 360 | Line 367 | public class StampedLockTest extends JSR
367       */
368      public void testInterruptibleOperationsThrowInterruptedExceptionReadLockedInterrupted() {
369          final StampedLock lock = new StampedLock();
370 <        long s = lock.readLock();
370 >        long stamp = lock.readLock();
371  
372          Action[] interruptibleLockBlockingActions = {
373              () -> lock.writeLockInterruptibly(),
# Line 371 | Line 378 | public class StampedLockTest extends JSR
378          shuffle(interruptibleLockBlockingActions);
379  
380          assertThrowInterruptedExceptionWhenInterrupted(interruptibleLockBlockingActions);
381 +
382 +        releaseReadLock(lock, stamp);
383      }
384  
385      /**
# Line 582 | Line 591 | public class StampedLockTest extends JSR
591          long s = lock.readLock();
592          Thread t = newStartedThread(new CheckedRunnable() {
593              public void realRun() {
594 <                threadAssertEquals(0L, lock.tryWriteLock());
594 >                assertEquals(0L, lock.tryWriteLock());
595              }});
596  
597          awaitTermination(t);
# Line 694 | Line 703 | public class StampedLockTest extends JSR
703          lock.unlockWrite(s);
704          s = lock.readLock();
705          assertTrue(lock.toString().contains("Read-locks"));
706 +        releaseReadLock(lock, s);
707      }
708  
709      /**
# Line 977 | Line 987 | public class StampedLockTest extends JSR
987       * IllegalMonitorStateException
988       */
989      public void testCannotUnlockOptimisticReadStamps() {
990 <        Runnable[] actions = {
991 <            () -> {
992 <                StampedLock sl = new StampedLock();
993 <                long stamp = assertValid(sl, sl.tryOptimisticRead());
994 <                sl.unlockRead(stamp);
995 <            },
996 <            () -> {
997 <                StampedLock sl = new StampedLock();
998 <                long stamp = sl.tryOptimisticRead();
999 <                sl.unlock(stamp);
1000 <            },
1001 <
992 <            () -> {
993 <                StampedLock sl = new StampedLock();
994 <                long stamp = sl.tryOptimisticRead();
995 <                sl.writeLock();
996 <                sl.unlock(stamp);
997 <            },
998 <            () -> {
999 <                StampedLock sl = new StampedLock();
1000 <                sl.readLock();
1001 <                long stamp = assertValid(sl, sl.tryOptimisticRead());
1002 <                sl.unlockRead(stamp);
1003 <            },
1004 <            () -> {
1005 <                StampedLock sl = new StampedLock();
1006 <                sl.readLock();
1007 <                long stamp = assertValid(sl, sl.tryOptimisticRead());
1008 <                sl.unlock(stamp);
1009 <            },
990 >        {
991 >            StampedLock sl = new StampedLock();
992 >            long stamp = assertValid(sl, sl.tryOptimisticRead());
993 >            assertThrows(IllegalMonitorStateException.class,
994 >                () -> sl.unlockRead(stamp));
995 >        }
996 >        {
997 >            StampedLock sl = new StampedLock();
998 >            long stamp = sl.tryOptimisticRead();
999 >            assertThrows(IllegalMonitorStateException.class,
1000 >                () -> sl.unlock(stamp));
1001 >        }
1002  
1003 <            () -> {
1004 <                StampedLock sl = new StampedLock();
1005 <                long stamp = sl.tryConvertToOptimisticRead(sl.writeLock());
1006 <                assertValid(sl, stamp);
1007 <                sl.writeLock();
1008 <                sl.unlockWrite(stamp);
1009 <            },
1010 <            () -> {
1011 <                StampedLock sl = new StampedLock();
1012 <                long stamp = sl.tryConvertToOptimisticRead(sl.writeLock());
1013 <                sl.writeLock();
1014 <                sl.unlock(stamp);
1015 <            },
1016 <            () -> {
1017 <                StampedLock sl = new StampedLock();
1018 <                long stamp = sl.tryConvertToOptimisticRead(sl.writeLock());
1019 <                sl.readLock();
1020 <                sl.unlockRead(stamp);
1021 <            },
1022 <            () -> {
1023 <                StampedLock sl = new StampedLock();
1032 <                long stamp = sl.tryConvertToOptimisticRead(sl.writeLock());
1033 <                sl.readLock();
1034 <                sl.unlock(stamp);
1035 <            },
1003 >        {
1004 >            StampedLock sl = new StampedLock();
1005 >            long stamp = sl.tryOptimisticRead();
1006 >            sl.writeLock();
1007 >            assertThrows(IllegalMonitorStateException.class,
1008 >                () -> sl.unlock(stamp));
1009 >        }
1010 >        {
1011 >            StampedLock sl = new StampedLock();
1012 >            sl.readLock();
1013 >            long stamp = assertValid(sl, sl.tryOptimisticRead());
1014 >            assertThrows(IllegalMonitorStateException.class,
1015 >                () -> sl.unlockRead(stamp));
1016 >        }
1017 >        {
1018 >            StampedLock sl = new StampedLock();
1019 >            sl.readLock();
1020 >            long stamp = assertValid(sl, sl.tryOptimisticRead());
1021 >            assertThrows(IllegalMonitorStateException.class,
1022 >                () -> sl.unlock(stamp));
1023 >        }
1024  
1025 <            () -> {
1026 <                StampedLock sl = new StampedLock();
1027 <                long stamp = sl.tryConvertToOptimisticRead(sl.readLock());
1028 <                assertValid(sl, stamp);
1029 <                sl.writeLock();
1030 <                sl.unlockWrite(stamp);
1031 <            },
1032 <            () -> {
1033 <                StampedLock sl = new StampedLock();
1034 <                long stamp = sl.tryConvertToOptimisticRead(sl.readLock());
1035 <                sl.writeLock();
1036 <                sl.unlock(stamp);
1037 <            },
1038 <            () -> {
1039 <                StampedLock sl = new StampedLock();
1040 <                long stamp = sl.tryConvertToOptimisticRead(sl.readLock());
1041 <                sl.readLock();
1042 <                sl.unlockRead(stamp);
1043 <            },
1044 <            () -> {
1045 <                StampedLock sl = new StampedLock();
1046 <                sl.readLock();
1047 <                long stamp = sl.tryConvertToOptimisticRead(sl.readLock());
1048 <                assertValid(sl, stamp);
1049 <                sl.readLock();
1050 <                sl.unlockRead(stamp);
1051 <            },
1052 <            () -> {
1053 <                StampedLock sl = new StampedLock();
1066 <                long stamp = sl.tryConvertToOptimisticRead(sl.readLock());
1067 <                sl.readLock();
1068 <                sl.unlock(stamp);
1069 <            },
1070 <            () -> {
1071 <                StampedLock sl = new StampedLock();
1072 <                sl.readLock();
1073 <                long stamp = sl.tryConvertToOptimisticRead(sl.readLock());
1074 <                sl.readLock();
1075 <                sl.unlock(stamp);
1076 <            },
1077 <        };
1025 >        {
1026 >            StampedLock sl = new StampedLock();
1027 >            long stamp = sl.tryConvertToOptimisticRead(sl.writeLock());
1028 >            assertValid(sl, stamp);
1029 >            sl.writeLock();
1030 >            assertThrows(IllegalMonitorStateException.class,
1031 >                () -> sl.unlockWrite(stamp));
1032 >        }
1033 >        {
1034 >            StampedLock sl = new StampedLock();
1035 >            long stamp = sl.tryConvertToOptimisticRead(sl.writeLock());
1036 >            sl.writeLock();
1037 >            assertThrows(IllegalMonitorStateException.class,
1038 >                () -> sl.unlock(stamp));
1039 >        }
1040 >        {
1041 >            StampedLock sl = new StampedLock();
1042 >            long stamp = sl.tryConvertToOptimisticRead(sl.writeLock());
1043 >            sl.readLock();
1044 >            assertThrows(IllegalMonitorStateException.class,
1045 >                () -> sl.unlockRead(stamp));
1046 >        }
1047 >        {
1048 >            StampedLock sl = new StampedLock();
1049 >            long stamp = sl.tryConvertToOptimisticRead(sl.writeLock());
1050 >            sl.readLock();
1051 >            assertThrows(IllegalMonitorStateException.class,
1052 >                () -> sl.unlock(stamp));
1053 >        }
1054  
1055 <        assertThrows(IllegalMonitorStateException.class, actions);
1055 >        {
1056 >            StampedLock sl = new StampedLock();
1057 >            long stamp = sl.tryConvertToOptimisticRead(sl.readLock());
1058 >            assertValid(sl, stamp);
1059 >            sl.writeLock();
1060 >            assertThrows(IllegalMonitorStateException.class,
1061 >                () -> sl.unlockWrite(stamp));
1062 >            }
1063 >        {
1064 >            StampedLock sl = new StampedLock();
1065 >            long stamp = sl.tryConvertToOptimisticRead(sl.readLock());
1066 >            sl.writeLock();
1067 >            assertThrows(IllegalMonitorStateException.class,
1068 >                () -> sl.unlock(stamp));
1069 >        }
1070 >        {
1071 >            StampedLock sl = new StampedLock();
1072 >            long stamp = sl.tryConvertToOptimisticRead(sl.readLock());
1073 >            sl.readLock();
1074 >            assertThrows(IllegalMonitorStateException.class,
1075 >                () -> sl.unlockRead(stamp));
1076 >        }
1077 >        {
1078 >            StampedLock sl = new StampedLock();
1079 >            sl.readLock();
1080 >            long stamp = sl.tryConvertToOptimisticRead(sl.readLock());
1081 >            assertValid(sl, stamp);
1082 >            sl.readLock();
1083 >            assertThrows(IllegalMonitorStateException.class,
1084 >                () -> sl.unlockRead(stamp));
1085 >        }
1086 >        {
1087 >            StampedLock sl = new StampedLock();
1088 >            long stamp = sl.tryConvertToOptimisticRead(sl.readLock());
1089 >            sl.readLock();
1090 >            assertThrows(IllegalMonitorStateException.class,
1091 >                () -> sl.unlock(stamp));
1092 >        }
1093 >        {
1094 >            StampedLock sl = new StampedLock();
1095 >            sl.readLock();
1096 >            long stamp = sl.tryConvertToOptimisticRead(sl.readLock());
1097 >            sl.readLock();
1098 >            assertThrows(IllegalMonitorStateException.class,
1099 >                () -> sl.unlock(stamp));
1100 >        }
1101      }
1102  
1103      static long writeLockInterruptiblyUninterrupted(StampedLock sl) {
# Line 1259 | Line 1280 | public class StampedLockTest extends JSR
1280                  } while (stamp == 0);
1281                  return Math.hypot(currentX, currentY);
1282              }
1283 +
1284 +            double distanceFromOrigin2() {
1285 +                long stamp = sl.tryOptimisticRead();
1286 +                try {
1287 +                    retryHoldingLock:
1288 +                    for (;; stamp = sl.readLock()) {
1289 +                        if (stamp == 0L)
1290 +                            continue retryHoldingLock;
1291 +                        // possibly racy reads
1292 +                        double currentX = x;
1293 +                        double currentY = y;
1294 +                        if (!sl.validate(stamp))
1295 +                            continue retryHoldingLock;
1296 +                        return Math.hypot(currentX, currentY);
1297 +                    }
1298 +                } finally {
1299 +                    if (StampedLock.isReadLockStamp(stamp))
1300 +                        sl.unlockRead(stamp);
1301 +                }
1302 +            }
1303 +
1304 +            void moveIfAtOrigin(double newX, double newY) {
1305 +                long stamp = sl.readLock();
1306 +                try {
1307 +                    while (x == 0.0 && y == 0.0) {
1308 +                        long ws = sl.tryConvertToWriteLock(stamp);
1309 +                        if (ws != 0L) {
1310 +                            stamp = ws;
1311 +                            x = newX;
1312 +                            y = newY;
1313 +                            return;
1314 +                        }
1315 +                        else {
1316 +                            sl.unlockRead(stamp);
1317 +                            stamp = sl.writeLock();
1318 +                        }
1319 +                    }
1320 +                } finally {
1321 +                    sl.unlock(stamp);
1322 +                }
1323 +            }
1324          }
1325  
1326          Point p = new Point();
1327          p.move(3.0, 4.0);
1328          assertEquals(5.0, p.distanceFromOrigin());
1329 +        p.moveIfAtOrigin(5.0, 12.0);
1330 +        assertEquals(5.0, p.distanceFromOrigin2());
1331      }
1332 <    
1332 >
1333 >    /**
1334 >     * Stamp inspection methods work as expected, and do not inspect
1335 >     * the state of the lock itself.
1336 >     */
1337 >    public void testStampStateInspectionMethods() {
1338 >        StampedLock lock = new StampedLock();
1339 >
1340 >        assertFalse(isWriteLockStamp(0L));
1341 >        assertFalse(isReadLockStamp(0L));
1342 >        assertFalse(isLockStamp(0L));
1343 >        assertFalse(isOptimisticReadStamp(0L));
1344 >
1345 >        {
1346 >            long stamp = lock.writeLock();
1347 >            for (int i = 0; i < 2; i++) {
1348 >                assertTrue(isWriteLockStamp(stamp));
1349 >                assertFalse(isReadLockStamp(stamp));
1350 >                assertTrue(isLockStamp(stamp));
1351 >                assertFalse(isOptimisticReadStamp(stamp));
1352 >                if (i == 0)
1353 >                    lock.unlockWrite(stamp);
1354 >            }
1355 >        }
1356 >
1357 >        {
1358 >            long stamp = lock.readLock();
1359 >            for (int i = 0; i < 2; i++) {
1360 >                assertFalse(isWriteLockStamp(stamp));
1361 >                assertTrue(isReadLockStamp(stamp));
1362 >                assertTrue(isLockStamp(stamp));
1363 >                assertFalse(isOptimisticReadStamp(stamp));
1364 >                if (i == 0)
1365 >                    lock.unlockRead(stamp);
1366 >            }
1367 >        }
1368 >
1369 >        {
1370 >            long optimisticStamp = lock.tryOptimisticRead();
1371 >            long readStamp = lock.tryConvertToReadLock(optimisticStamp);
1372 >            long writeStamp = lock.tryConvertToWriteLock(readStamp);
1373 >            for (int i = 0; i < 2; i++) {
1374 >                assertFalse(isWriteLockStamp(optimisticStamp));
1375 >                assertFalse(isReadLockStamp(optimisticStamp));
1376 >                assertFalse(isLockStamp(optimisticStamp));
1377 >                assertTrue(isOptimisticReadStamp(optimisticStamp));
1378 >
1379 >                assertFalse(isWriteLockStamp(readStamp));
1380 >                assertTrue(isReadLockStamp(readStamp));
1381 >                assertTrue(isLockStamp(readStamp));
1382 >                assertFalse(isOptimisticReadStamp(readStamp));
1383 >
1384 >                assertTrue(isWriteLockStamp(writeStamp));
1385 >                assertFalse(isReadLockStamp(writeStamp));
1386 >                assertTrue(isLockStamp(writeStamp));
1387 >                assertFalse(isOptimisticReadStamp(writeStamp));
1388 >                if (i == 0)
1389 >                    lock.unlockWrite(writeStamp);
1390 >            }
1391 >        }
1392 >    }
1393 >
1394 >    /**
1395 >     * Multiple threads repeatedly contend for the same lock.
1396 >     */
1397 >    public void testConcurrentAccess() throws Exception {
1398 >        final StampedLock sl = new StampedLock();
1399 >        final Lock wl = sl.asWriteLock();
1400 >        final Lock rl = sl.asReadLock();
1401 >        final long testDurationMillis = expensiveTests ? 1000 : 2;
1402 >        final int nTasks = ThreadLocalRandom.current().nextInt(1, 10);
1403 >        final AtomicBoolean done = new AtomicBoolean(false);
1404 >        final List<CompletableFuture> futures = new ArrayList<>();
1405 >        final List<Callable<Long>> stampedWriteLockers = List.of(
1406 >            () -> sl.writeLock(),
1407 >            () -> writeLockInterruptiblyUninterrupted(sl),
1408 >            () -> tryWriteLockUninterrupted(sl, LONG_DELAY_MS, MILLISECONDS),
1409 >            () -> {
1410 >                long stamp;
1411 >                do { stamp = sl.tryConvertToWriteLock(sl.tryOptimisticRead()); }
1412 >                while (stamp == 0L);
1413 >                return stamp;
1414 >            },
1415 >            () -> {
1416 >              long stamp;
1417 >              do { stamp = sl.tryWriteLock(); } while (stamp == 0L);
1418 >              return stamp;
1419 >            },
1420 >            () -> {
1421 >              long stamp;
1422 >              do { stamp = sl.tryWriteLock(0L, DAYS); } while (stamp == 0L);
1423 >              return stamp;
1424 >            });
1425 >        final List<Callable<Long>> stampedReadLockers = List.of(
1426 >            () -> sl.readLock(),
1427 >            () -> readLockInterruptiblyUninterrupted(sl),
1428 >            () -> tryReadLockUninterrupted(sl, LONG_DELAY_MS, MILLISECONDS),
1429 >            () -> {
1430 >                long stamp;
1431 >                do { stamp = sl.tryConvertToReadLock(sl.tryOptimisticRead()); }
1432 >                while (stamp == 0L);
1433 >                return stamp;
1434 >            },
1435 >            () -> {
1436 >              long stamp;
1437 >              do { stamp = sl.tryReadLock(); } while (stamp == 0L);
1438 >              return stamp;
1439 >            },
1440 >            () -> {
1441 >              long stamp;
1442 >              do { stamp = sl.tryReadLock(0L, DAYS); } while (stamp == 0L);
1443 >              return stamp;
1444 >            });
1445 >        final List<Consumer<Long>> stampedWriteUnlockers = List.of(
1446 >            stamp -> sl.unlockWrite(stamp),
1447 >            stamp -> sl.unlock(stamp),
1448 >            stamp -> assertTrue(sl.tryUnlockWrite()),
1449 >            stamp -> wl.unlock(),
1450 >            stamp -> sl.tryConvertToOptimisticRead(stamp));
1451 >        final List<Consumer<Long>> stampedReadUnlockers = List.of(
1452 >            stamp -> sl.unlockRead(stamp),
1453 >            stamp -> sl.unlock(stamp),
1454 >            stamp -> assertTrue(sl.tryUnlockRead()),
1455 >            stamp -> rl.unlock(),
1456 >            stamp -> sl.tryConvertToOptimisticRead(stamp));
1457 >        final Action writer = () -> {
1458 >            // repeatedly acquires write lock
1459 >            var locker = chooseRandomly(stampedWriteLockers);
1460 >            var unlocker = chooseRandomly(stampedWriteUnlockers);
1461 >            while (!done.getAcquire()) {
1462 >                long stamp = locker.call();
1463 >                try {
1464 >                    assertTrue(isWriteLockStamp(stamp));
1465 >                    assertTrue(sl.isWriteLocked());
1466 >                    assertFalse(isReadLockStamp(stamp));
1467 >                    assertFalse(sl.isReadLocked());
1468 >                    assertEquals(0, sl.getReadLockCount());
1469 >                    assertTrue(sl.validate(stamp));
1470 >                } finally {
1471 >                    unlocker.accept(stamp);
1472 >                }
1473 >            }
1474 >        };
1475 >        final Action reader = () -> {
1476 >            // repeatedly acquires read lock
1477 >            var locker = chooseRandomly(stampedReadLockers);
1478 >            var unlocker = chooseRandomly(stampedReadUnlockers);
1479 >            while (!done.getAcquire()) {
1480 >                long stamp = locker.call();
1481 >                try {
1482 >                    assertFalse(isWriteLockStamp(stamp));
1483 >                    assertFalse(sl.isWriteLocked());
1484 >                    assertTrue(isReadLockStamp(stamp));
1485 >                    assertTrue(sl.isReadLocked());
1486 >                    assertTrue(sl.getReadLockCount() > 0);
1487 >                    assertTrue(sl.validate(stamp));
1488 >                } finally {
1489 >                    unlocker.accept(stamp);
1490 >                }
1491 >            }
1492 >        };
1493 >        for (int i = nTasks; i--> 0; ) {
1494 >            Action task = chooseRandomly(writer, reader);
1495 >            futures.add(CompletableFuture.runAsync(checkedRunnable(task)));
1496 >        }
1497 >        Thread.sleep(testDurationMillis);
1498 >        done.setRelease(true);
1499 >        for (var future : futures)
1500 >            checkTimedGet(future, null);
1501 >    }
1502 >
1503   }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines