ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/test/tck/StampedLockTest.java
Revision: 1.45
Committed: Wed Aug 12 16:12:23 2020 UTC (3 years, 9 months ago) by jsr166
Branch: MAIN
Changes since 1.44: +6 -2 lines
Log Message:
fix errorprone [UnusedVariable]

File Contents

# User Rev Content
1 jsr166 1.1 /*
2     * Written by Doug Lea and Martin Buchholz
3     * with assistance from members of JCP JSR-166 Expert Group and
4     * released to the public domain, as explained at
5     * http://creativecommons.org/publicdomain/zero/1.0/
6     */
7    
8 jsr166 1.25 import static java.util.concurrent.TimeUnit.DAYS;
9 jsr166 1.10 import static java.util.concurrent.TimeUnit.MILLISECONDS;
10    
11 jsr166 1.41 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 jsr166 1.25 import java.util.ArrayList;
17     import java.util.List;
18 jsr166 1.44 import java.util.concurrent.Callable;
19     import java.util.concurrent.CompletableFuture;
20 jsr166 1.10 import java.util.concurrent.CountDownLatch;
21 jsr166 1.27 import java.util.concurrent.Future;
22 jsr166 1.44 import java.util.concurrent.ThreadLocalRandom;
23 jsr166 1.25 import java.util.concurrent.TimeUnit;
24 jsr166 1.44 import java.util.concurrent.atomic.AtomicBoolean;
25 jsr166 1.1 import java.util.concurrent.locks.Lock;
26 jsr166 1.2 import java.util.concurrent.locks.StampedLock;
27 jsr166 1.25 import java.util.function.BiConsumer;
28 jsr166 1.44 import java.util.function.Consumer;
29 jsr166 1.25 import java.util.function.Function;
30 jsr166 1.10
31     import junit.framework.Test;
32     import junit.framework.TestSuite;
33 jsr166 1.1
34     public class StampedLockTest extends JSR166TestCase {
35     public static void main(String[] args) {
36 jsr166 1.13 main(suite(), args);
37 jsr166 1.1 }
38     public static Test suite() {
39     return new TestSuite(StampedLockTest.class);
40     }
41    
42 dl 1.4 /**
43 jsr166 1.27 * Releases write lock, checking isWriteLocked before and after
44 dl 1.4 */
45 jsr166 1.27 void releaseWriteLock(StampedLock lock, long stamp) {
46     assertTrue(lock.isWriteLocked());
47     assertValid(lock, stamp);
48     lock.unlockWrite(stamp);
49     assertFalse(lock.isWriteLocked());
50     assertFalse(lock.validate(stamp));
51 dl 1.4 }
52    
53     /**
54 jsr166 1.27 * Releases read lock, checking isReadLocked before and after
55 dl 1.4 */
56 jsr166 1.27 void releaseReadLock(StampedLock lock, long stamp) {
57     assertTrue(lock.isReadLocked());
58     assertValid(lock, stamp);
59     lock.unlockRead(stamp);
60     assertFalse(lock.isReadLocked());
61     assertTrue(lock.validate(stamp));
62 dl 1.4 }
63    
64 jsr166 1.27 long assertNonZero(long v) {
65     assertTrue(v != 0L);
66     return v;
67 dl 1.4 }
68    
69 jsr166 1.27 long assertValid(StampedLock lock, long stamp) {
70     assertTrue(stamp != 0L);
71     assertTrue(lock.validate(stamp));
72     return stamp;
73 dl 1.4 }
74    
75 jsr166 1.27 void assertUnlocked(StampedLock lock) {
76 dl 1.4 assertFalse(lock.isReadLocked());
77     assertFalse(lock.isWriteLocked());
78 jsr166 1.27 assertEquals(0, lock.getReadLockCount());
79     assertValid(lock, lock.tryOptimisticRead());
80     }
81    
82     List<Action> lockLockers(Lock lock) {
83 jsr166 1.44 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 jsr166 1.27 }
91    
92     List<Function<StampedLock, Long>> readLockers() {
93 jsr166 1.44 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 dl 1.4 }
101    
102 jsr166 1.27 List<BiConsumer<StampedLock, Long>> readUnlockers() {
103 jsr166 1.44 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 dl 1.4 }
110    
111 jsr166 1.27 List<Function<StampedLock, Long>> writeLockers() {
112 jsr166 1.44 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 dl 1.4 }
120    
121 jsr166 1.27 List<BiConsumer<StampedLock, Long>> writeUnlockers() {
122 jsr166 1.44 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 dl 1.4 }
129    
130     /**
131 jsr166 1.27 * Constructed StampedLock is in unlocked state
132 dl 1.4 */
133 jsr166 1.27 public void testConstructor() {
134     assertUnlocked(new StampedLock());
135 dl 1.4 }
136    
137     /**
138 jsr166 1.27 * write-locking, then unlocking, an unlocked lock succeed
139 dl 1.4 */
140 jsr166 1.27 public void testWriteLock_lockUnlock() {
141 dl 1.4 StampedLock lock = new StampedLock();
142 jsr166 1.27
143     for (Function<StampedLock, Long> writeLocker : writeLockers())
144     for (BiConsumer<StampedLock, Long> writeUnlocker : writeUnlockers()) {
145     assertFalse(lock.isWriteLocked());
146     assertFalse(lock.isReadLocked());
147     assertEquals(0, lock.getReadLockCount());
148    
149     long s = writeLocker.apply(lock);
150     assertValid(lock, s);
151     assertTrue(lock.isWriteLocked());
152     assertFalse(lock.isReadLocked());
153     assertEquals(0, lock.getReadLockCount());
154     writeUnlocker.accept(lock, s);
155     assertUnlocked(lock);
156     }
157 dl 1.4 }
158    
159     /**
160 jsr166 1.27 * read-locking, then unlocking, an unlocked lock succeed
161 dl 1.4 */
162 jsr166 1.27 public void testReadLock_lockUnlock() {
163 dl 1.4 StampedLock lock = new StampedLock();
164 jsr166 1.27
165     for (Function<StampedLock, Long> readLocker : readLockers())
166     for (BiConsumer<StampedLock, Long> readUnlocker : readUnlockers()) {
167     long s = 42;
168     for (int i = 0; i < 2; i++) {
169     s = assertValid(lock, readLocker.apply(lock));
170     assertFalse(lock.isWriteLocked());
171     assertTrue(lock.isReadLocked());
172     assertEquals(i + 1, lock.getReadLockCount());
173     }
174     for (int i = 0; i < 2; i++) {
175     assertFalse(lock.isWriteLocked());
176     assertTrue(lock.isReadLocked());
177     assertEquals(2 - i, lock.getReadLockCount());
178     readUnlocker.accept(lock, s);
179     }
180     assertUnlocked(lock);
181     }
182 dl 1.4 }
183    
184     /**
185 jsr166 1.27 * tryUnlockWrite fails if not write locked
186 dl 1.4 */
187 jsr166 1.27 public void testTryUnlockWrite_failure() {
188 dl 1.4 StampedLock lock = new StampedLock();
189 jsr166 1.27 assertFalse(lock.tryUnlockWrite());
190    
191     for (Function<StampedLock, Long> readLocker : readLockers())
192     for (BiConsumer<StampedLock, Long> readUnlocker : readUnlockers()) {
193     long s = assertValid(lock, readLocker.apply(lock));
194     assertFalse(lock.tryUnlockWrite());
195     assertTrue(lock.isReadLocked());
196     readUnlocker.accept(lock, s);
197     assertUnlocked(lock);
198     }
199 dl 1.4 }
200    
201     /**
202 jsr166 1.27 * tryUnlockRead fails if not read locked
203 dl 1.4 */
204 jsr166 1.27 public void testTryUnlockRead_failure() {
205 dl 1.4 StampedLock lock = new StampedLock();
206 jsr166 1.27 assertFalse(lock.tryUnlockRead());
207    
208     for (Function<StampedLock, Long> writeLocker : writeLockers())
209     for (BiConsumer<StampedLock, Long> writeUnlocker : writeUnlockers()) {
210     long s = writeLocker.apply(lock);
211     assertFalse(lock.tryUnlockRead());
212     assertTrue(lock.isWriteLocked());
213     writeUnlocker.accept(lock, s);
214     assertUnlocked(lock);
215     }
216 dl 1.4 }
217    
218     /**
219 jsr166 1.27 * validate(0L) fails
220 dl 1.4 */
221     public void testValidate0() {
222     StampedLock lock = new StampedLock();
223     assertFalse(lock.validate(0L));
224     }
225    
226     /**
227 jsr166 1.27 * A stamp obtained from a successful lock operation validates while the lock is held
228 dl 1.4 */
229 jsr166 1.11 public void testValidate() throws InterruptedException {
230     StampedLock lock = new StampedLock();
231 jsr166 1.27
232     for (Function<StampedLock, Long> readLocker : readLockers())
233     for (BiConsumer<StampedLock, Long> readUnlocker : readUnlockers()) {
234     long s = assertNonZero(readLocker.apply(lock));
235     assertTrue(lock.validate(s));
236     readUnlocker.accept(lock, s);
237     }
238    
239     for (Function<StampedLock, Long> writeLocker : writeLockers())
240     for (BiConsumer<StampedLock, Long> writeUnlocker : writeUnlockers()) {
241     long s = assertNonZero(writeLocker.apply(lock));
242     assertTrue(lock.validate(s));
243     writeUnlocker.accept(lock, s);
244     }
245 dl 1.4 }
246    
247     /**
248     * A stamp obtained from an unsuccessful lock operation does not validate
249     */
250 jsr166 1.11 public void testValidate2() throws InterruptedException {
251     StampedLock lock = new StampedLock();
252 jsr166 1.27 long s = assertNonZero(lock.writeLock());
253 jsr166 1.11 assertTrue(lock.validate(s));
254     assertFalse(lock.validate(lock.tryWriteLock()));
255 jsr166 1.36 assertFalse(lock.validate(lock.tryWriteLock(randomExpiredTimeout(),
256     randomTimeUnit())));
257 jsr166 1.11 assertFalse(lock.validate(lock.tryReadLock()));
258 jsr166 1.36 assertFalse(lock.validate(lock.tryWriteLock(randomExpiredTimeout(),
259     randomTimeUnit())));
260 jsr166 1.11 assertFalse(lock.validate(lock.tryOptimisticRead()));
261     lock.unlockWrite(s);
262 dl 1.4 }
263    
264 jsr166 1.27 void assertThrowInterruptedExceptionWhenPreInterrupted(Action[] actions) {
265     for (Action action : actions) {
266     Thread.currentThread().interrupt();
267     try {
268     action.run();
269     shouldThrow();
270     }
271     catch (InterruptedException success) {}
272     catch (Throwable fail) { threadUnexpectedException(fail); }
273     assertFalse(Thread.interrupted());
274     }
275     }
276    
277 dl 1.4 /**
278 jsr166 1.27 * interruptible operations throw InterruptedException when pre-interrupted
279 dl 1.4 */
280 jsr166 1.27 public void testInterruptibleOperationsThrowInterruptedExceptionWhenPreInterrupted() {
281 dl 1.4 final StampedLock lock = new StampedLock();
282 jsr166 1.12
283 jsr166 1.27 Action[] interruptibleLockActions = {
284     () -> lock.writeLockInterruptibly(),
285     () -> lock.tryWriteLock(Long.MIN_VALUE, DAYS),
286     () -> lock.tryWriteLock(Long.MAX_VALUE, DAYS),
287     () -> lock.readLockInterruptibly(),
288     () -> lock.tryReadLock(Long.MIN_VALUE, DAYS),
289     () -> lock.tryReadLock(Long.MAX_VALUE, DAYS),
290     () -> lock.asWriteLock().lockInterruptibly(),
291     () -> lock.asWriteLock().tryLock(0L, DAYS),
292     () -> lock.asWriteLock().tryLock(Long.MAX_VALUE, DAYS),
293     () -> lock.asReadLock().lockInterruptibly(),
294     () -> lock.asReadLock().tryLock(0L, DAYS),
295     () -> lock.asReadLock().tryLock(Long.MAX_VALUE, DAYS),
296     };
297     shuffle(interruptibleLockActions);
298    
299     assertThrowInterruptedExceptionWhenPreInterrupted(interruptibleLockActions);
300     {
301     long s = lock.writeLock();
302     assertThrowInterruptedExceptionWhenPreInterrupted(interruptibleLockActions);
303     lock.unlockWrite(s);
304     }
305     {
306     long s = lock.readLock();
307     assertThrowInterruptedExceptionWhenPreInterrupted(interruptibleLockActions);
308     lock.unlockRead(s);
309     }
310     }
311    
312     void assertThrowInterruptedExceptionWhenInterrupted(Action[] actions) {
313     int n = actions.length;
314     Future<?>[] futures = new Future<?>[n];
315     CountDownLatch threadsStarted = new CountDownLatch(n);
316     CountDownLatch done = new CountDownLatch(n);
317    
318     for (int i = 0; i < n; i++) {
319     Action action = actions[i];
320     futures[i] = cachedThreadPool.submit(new CheckedRunnable() {
321     public void realRun() throws Throwable {
322     threadsStarted.countDown();
323     try {
324     action.run();
325     shouldThrow();
326     }
327     catch (InterruptedException success) {}
328     catch (Throwable fail) { threadUnexpectedException(fail); }
329     assertFalse(Thread.interrupted());
330     done.countDown();
331     }});
332     }
333    
334     await(threadsStarted);
335     assertEquals(n, done.getCount());
336     for (Future<?> future : futures) // Interrupt all the tasks
337     future.cancel(true);
338     await(done);
339 dl 1.4 }
340    
341     /**
342 jsr166 1.27 * interruptible operations throw InterruptedException when write locked and interrupted
343 dl 1.4 */
344 jsr166 1.27 public void testInterruptibleOperationsThrowInterruptedExceptionWriteLockedInterrupted() {
345 dl 1.4 final StampedLock lock = new StampedLock();
346 jsr166 1.45 long stamp = lock.writeLock();
347 jsr166 1.12
348 jsr166 1.27 Action[] interruptibleLockBlockingActions = {
349     () -> lock.writeLockInterruptibly(),
350     () -> lock.tryWriteLock(Long.MAX_VALUE, DAYS),
351     () -> lock.readLockInterruptibly(),
352     () -> lock.tryReadLock(Long.MAX_VALUE, DAYS),
353     () -> lock.asWriteLock().lockInterruptibly(),
354     () -> lock.asWriteLock().tryLock(Long.MAX_VALUE, DAYS),
355     () -> lock.asReadLock().lockInterruptibly(),
356     () -> lock.asReadLock().tryLock(Long.MAX_VALUE, DAYS),
357     };
358     shuffle(interruptibleLockBlockingActions);
359    
360     assertThrowInterruptedExceptionWhenInterrupted(interruptibleLockBlockingActions);
361 jsr166 1.45
362     releaseWriteLock(lock, stamp);
363 dl 1.4 }
364    
365     /**
366 jsr166 1.27 * interruptible operations throw InterruptedException when read locked and interrupted
367 dl 1.4 */
368 jsr166 1.27 public void testInterruptibleOperationsThrowInterruptedExceptionReadLockedInterrupted() {
369 dl 1.4 final StampedLock lock = new StampedLock();
370 jsr166 1.45 long stamp = lock.readLock();
371 jsr166 1.27
372     Action[] interruptibleLockBlockingActions = {
373     () -> lock.writeLockInterruptibly(),
374     () -> lock.tryWriteLock(Long.MAX_VALUE, DAYS),
375     () -> lock.asWriteLock().lockInterruptibly(),
376     () -> lock.asWriteLock().tryLock(Long.MAX_VALUE, DAYS),
377     };
378     shuffle(interruptibleLockBlockingActions);
379 jsr166 1.12
380 jsr166 1.27 assertThrowInterruptedExceptionWhenInterrupted(interruptibleLockBlockingActions);
381 jsr166 1.45
382     releaseReadLock(lock, stamp);
383 dl 1.4 }
384    
385     /**
386 jsr166 1.27 * Non-interruptible operations ignore and preserve interrupt status
387 dl 1.4 */
388 jsr166 1.27 public void testNonInterruptibleOperationsIgnoreInterrupts() {
389 dl 1.4 final StampedLock lock = new StampedLock();
390 jsr166 1.27 Thread.currentThread().interrupt();
391    
392     for (BiConsumer<StampedLock, Long> readUnlocker : readUnlockers()) {
393     long s = assertValid(lock, lock.readLock());
394     readUnlocker.accept(lock, s);
395     s = assertValid(lock, lock.tryReadLock());
396     readUnlocker.accept(lock, s);
397     }
398    
399     lock.asReadLock().lock();
400     lock.asReadLock().unlock();
401    
402     for (BiConsumer<StampedLock, Long> writeUnlocker : writeUnlockers()) {
403     long s = assertValid(lock, lock.writeLock());
404     writeUnlocker.accept(lock, s);
405     s = assertValid(lock, lock.tryWriteLock());
406     writeUnlocker.accept(lock, s);
407     }
408    
409     lock.asWriteLock().lock();
410     lock.asWriteLock().unlock();
411 jsr166 1.12
412 jsr166 1.27 assertTrue(Thread.interrupted());
413 dl 1.4 }
414    
415     /**
416     * tryWriteLock on an unlocked lock succeeds
417     */
418 jsr166 1.27 public void testTryWriteLock() {
419 dl 1.4 final StampedLock lock = new StampedLock();
420     long s = lock.tryWriteLock();
421     assertTrue(s != 0L);
422     assertTrue(lock.isWriteLocked());
423 jsr166 1.27 assertEquals(0L, lock.tryWriteLock());
424 dl 1.4 releaseWriteLock(lock, s);
425     }
426    
427     /**
428     * tryWriteLock fails if locked
429     */
430 jsr166 1.27 public void testTryWriteLockWhenLocked() {
431 dl 1.4 final StampedLock lock = new StampedLock();
432     long s = lock.writeLock();
433     Thread t = newStartedThread(new CheckedRunnable() {
434     public void realRun() {
435 jsr166 1.27 assertEquals(0L, lock.tryWriteLock());
436 dl 1.4 }});
437 jsr166 1.12
438 jsr166 1.27 assertEquals(0L, lock.tryWriteLock());
439 dl 1.4 awaitTermination(t);
440     releaseWriteLock(lock, s);
441     }
442    
443     /**
444     * tryReadLock fails if write-locked
445     */
446 jsr166 1.27 public void testTryReadLockWhenLocked() {
447 dl 1.4 final StampedLock lock = new StampedLock();
448     long s = lock.writeLock();
449     Thread t = newStartedThread(new CheckedRunnable() {
450     public void realRun() {
451 jsr166 1.27 assertEquals(0L, lock.tryReadLock());
452 dl 1.4 }});
453 jsr166 1.12
454 jsr166 1.27 assertEquals(0L, lock.tryReadLock());
455 dl 1.4 awaitTermination(t);
456     releaseWriteLock(lock, s);
457     }
458    
459     /**
460     * Multiple threads can hold a read lock when not write-locked
461     */
462     public void testMultipleReadLocks() {
463     final StampedLock lock = new StampedLock();
464     final long s = lock.readLock();
465     Thread t = newStartedThread(new CheckedRunnable() {
466     public void realRun() throws InterruptedException {
467     long s2 = lock.tryReadLock();
468 jsr166 1.27 assertValid(lock, s2);
469 dl 1.4 lock.unlockRead(s2);
470     long s3 = lock.tryReadLock(LONG_DELAY_MS, MILLISECONDS);
471 jsr166 1.27 assertValid(lock, s3);
472 dl 1.4 lock.unlockRead(s3);
473     long s4 = lock.readLock();
474 jsr166 1.27 assertValid(lock, s4);
475 dl 1.4 lock.unlockRead(s4);
476 jsr166 1.27 lock.asReadLock().lock();
477     lock.asReadLock().unlock();
478     lock.asReadLock().lockInterruptibly();
479     lock.asReadLock().unlock();
480     lock.asReadLock().tryLock(Long.MIN_VALUE, DAYS);
481     lock.asReadLock().unlock();
482 dl 1.4 }});
483 jsr166 1.12
484 dl 1.4 awaitTermination(t);
485     lock.unlockRead(s);
486     }
487    
488     /**
489 jsr166 1.33 * writeLock() succeeds only after a reading thread unlocks
490 dl 1.4 */
491 jsr166 1.11 public void testWriteAfterReadLock() throws InterruptedException {
492 jsr166 1.33 final CountDownLatch aboutToLock = new CountDownLatch(1);
493 dl 1.4 final StampedLock lock = new StampedLock();
494     long rs = lock.readLock();
495     Thread t = newStartedThread(new CheckedRunnable() {
496     public void realRun() {
497 jsr166 1.33 aboutToLock.countDown();
498 dl 1.4 long s = lock.writeLock();
499 jsr166 1.33 assertTrue(lock.isWriteLocked());
500     assertFalse(lock.isReadLocked());
501 dl 1.4 lock.unlockWrite(s);
502     }});
503 jsr166 1.12
504 jsr166 1.34 await(aboutToLock);
505 jsr166 1.35 assertThreadBlocks(t, Thread.State.WAITING);
506 jsr166 1.11 assertFalse(lock.isWriteLocked());
507 jsr166 1.33 assertTrue(lock.isReadLocked());
508 jsr166 1.11 lock.unlockRead(rs);
509     awaitTermination(t);
510 jsr166 1.33 assertUnlocked(lock);
511 dl 1.4 }
512    
513     /**
514 jsr166 1.33 * writeLock() succeeds only after reading threads unlock
515 dl 1.4 */
516     public void testWriteAfterMultipleReadLocks() {
517     final StampedLock lock = new StampedLock();
518     long s = lock.readLock();
519     Thread t1 = newStartedThread(new CheckedRunnable() {
520     public void realRun() {
521     long rs = lock.readLock();
522     lock.unlockRead(rs);
523     }});
524 jsr166 1.12
525 dl 1.4 awaitTermination(t1);
526    
527     Thread t2 = newStartedThread(new CheckedRunnable() {
528     public void realRun() {
529     long ws = lock.writeLock();
530     lock.unlockWrite(ws);
531     }});
532 jsr166 1.12
533 jsr166 1.27 assertTrue(lock.isReadLocked());
534 dl 1.4 assertFalse(lock.isWriteLocked());
535     lock.unlockRead(s);
536     awaitTermination(t2);
537 jsr166 1.33 assertUnlocked(lock);
538 dl 1.4 }
539    
540     /**
541 jsr166 1.33 * readLock() succeed only after a writing thread unlocks
542 dl 1.4 */
543     public void testReadAfterWriteLock() {
544     final StampedLock lock = new StampedLock();
545 jsr166 1.27 final CountDownLatch threadsStarted = new CountDownLatch(2);
546 dl 1.4 final long s = lock.writeLock();
547 jsr166 1.33 final Runnable acquireReleaseReadLock = new CheckedRunnable() {
548 dl 1.4 public void realRun() {
549 jsr166 1.27 threadsStarted.countDown();
550 dl 1.4 long rs = lock.readLock();
551 jsr166 1.33 assertTrue(lock.isReadLocked());
552     assertFalse(lock.isWriteLocked());
553 dl 1.4 lock.unlockRead(rs);
554 jsr166 1.33 }};
555     Thread t1 = newStartedThread(acquireReleaseReadLock);
556     Thread t2 = newStartedThread(acquireReleaseReadLock);
557 dl 1.4
558 jsr166 1.27 await(threadsStarted);
559 jsr166 1.35 assertThreadBlocks(t1, Thread.State.WAITING);
560     assertThreadBlocks(t2, Thread.State.WAITING);
561 jsr166 1.33 assertTrue(lock.isWriteLocked());
562     assertFalse(lock.isReadLocked());
563 dl 1.4 releaseWriteLock(lock, s);
564     awaitTermination(t1);
565     awaitTermination(t2);
566 jsr166 1.33 assertUnlocked(lock);
567 dl 1.4 }
568    
569     /**
570 jsr166 1.27 * tryReadLock succeeds if read locked but not write locked
571 dl 1.4 */
572     public void testTryLockWhenReadLocked() {
573     final StampedLock lock = new StampedLock();
574     long s = lock.readLock();
575     Thread t = newStartedThread(new CheckedRunnable() {
576     public void realRun() {
577     long rs = lock.tryReadLock();
578 jsr166 1.27 assertValid(lock, rs);
579 dl 1.4 lock.unlockRead(rs);
580     }});
581    
582     awaitTermination(t);
583     lock.unlockRead(s);
584     }
585    
586     /**
587 jsr166 1.27 * tryWriteLock fails when read locked
588 dl 1.4 */
589 jsr166 1.27 public void testTryWriteLockWhenReadLocked() {
590 dl 1.4 final StampedLock lock = new StampedLock();
591     long s = lock.readLock();
592     Thread t = newStartedThread(new CheckedRunnable() {
593     public void realRun() {
594 jsr166 1.42 assertEquals(0L, lock.tryWriteLock());
595 dl 1.4 }});
596    
597     awaitTermination(t);
598     lock.unlockRead(s);
599     }
600    
601     /**
602 jsr166 1.27 * timed lock operations time out if lock not available
603 dl 1.4 */
604 jsr166 1.27 public void testTimedLock_Timeout() throws Exception {
605     ArrayList<Future<?>> futures = new ArrayList<>();
606    
607     // Write locked
608 dl 1.4 final StampedLock lock = new StampedLock();
609 jsr166 1.27 long stamp = lock.writeLock();
610     assertEquals(0L, lock.tryReadLock(0L, DAYS));
611     assertEquals(0L, lock.tryReadLock(Long.MIN_VALUE, DAYS));
612     assertFalse(lock.asReadLock().tryLock(0L, DAYS));
613     assertFalse(lock.asReadLock().tryLock(Long.MIN_VALUE, DAYS));
614     assertEquals(0L, lock.tryWriteLock(0L, DAYS));
615     assertEquals(0L, lock.tryWriteLock(Long.MIN_VALUE, DAYS));
616     assertFalse(lock.asWriteLock().tryLock(0L, DAYS));
617     assertFalse(lock.asWriteLock().tryLock(Long.MIN_VALUE, DAYS));
618    
619     futures.add(cachedThreadPool.submit(new CheckedRunnable() {
620 dl 1.4 public void realRun() throws InterruptedException {
621     long startTime = System.nanoTime();
622 jsr166 1.27 assertEquals(0L, lock.tryWriteLock(timeoutMillis(), MILLISECONDS));
623     assertTrue(millisElapsedSince(startTime) >= timeoutMillis());
624     }}));
625 dl 1.4
626 jsr166 1.27 futures.add(cachedThreadPool.submit(new CheckedRunnable() {
627     public void realRun() throws InterruptedException {
628     long startTime = System.nanoTime();
629     assertEquals(0L, lock.tryReadLock(timeoutMillis(), MILLISECONDS));
630     assertTrue(millisElapsedSince(startTime) >= timeoutMillis());
631     }}));
632    
633     // Read locked
634     final StampedLock lock2 = new StampedLock();
635     long stamp2 = lock2.readLock();
636     assertEquals(0L, lock2.tryWriteLock(0L, DAYS));
637     assertEquals(0L, lock2.tryWriteLock(Long.MIN_VALUE, DAYS));
638     assertFalse(lock2.asWriteLock().tryLock(0L, DAYS));
639     assertFalse(lock2.asWriteLock().tryLock(Long.MIN_VALUE, DAYS));
640 dl 1.4
641 jsr166 1.27 futures.add(cachedThreadPool.submit(new CheckedRunnable() {
642 dl 1.4 public void realRun() throws InterruptedException {
643     long startTime = System.nanoTime();
644 jsr166 1.27 assertEquals(0L, lock2.tryWriteLock(timeoutMillis(), MILLISECONDS));
645     assertTrue(millisElapsedSince(startTime) >= timeoutMillis());
646     }}));
647    
648     for (Future<?> future : futures)
649     assertNull(future.get());
650 jsr166 1.7
651 jsr166 1.27 releaseWriteLock(lock, stamp);
652     releaseReadLock(lock2, stamp2);
653 dl 1.4 }
654    
655     /**
656 jsr166 1.27 * writeLockInterruptibly succeeds if unlocked
657 dl 1.4 */
658 jsr166 1.11 public void testWriteLockInterruptibly() throws InterruptedException {
659 dl 1.4 final StampedLock lock = new StampedLock();
660 jsr166 1.11 long s = lock.writeLockInterruptibly();
661     assertTrue(lock.isWriteLocked());
662     releaseWriteLock(lock, s);
663 dl 1.4 }
664    
665     /**
666 jsr166 1.27 * readLockInterruptibly succeeds if lock free
667 dl 1.4 */
668 jsr166 1.11 public void testReadLockInterruptibly() throws InterruptedException {
669 dl 1.4 final StampedLock lock = new StampedLock();
670 jsr166 1.27
671     long s = assertValid(lock, lock.readLockInterruptibly());
672     assertTrue(lock.isReadLocked());
673 jsr166 1.11 lock.unlockRead(s);
674 jsr166 1.12
675 jsr166 1.27 lock.asReadLock().lockInterruptibly();
676     assertTrue(lock.isReadLocked());
677     lock.asReadLock().unlock();
678 dl 1.4 }
679    
680     /**
681     * A serialized lock deserializes as unlocked
682     */
683     public void testSerialization() {
684     StampedLock lock = new StampedLock();
685     lock.writeLock();
686     StampedLock clone = serialClone(lock);
687     assertTrue(lock.isWriteLocked());
688     assertFalse(clone.isWriteLocked());
689     long s = clone.writeLock();
690     assertTrue(clone.isWriteLocked());
691     clone.unlockWrite(s);
692     assertFalse(clone.isWriteLocked());
693     }
694 dl 1.5
695 dl 1.4 /**
696     * toString indicates current lock state
697     */
698     public void testToString() {
699     StampedLock lock = new StampedLock();
700     assertTrue(lock.toString().contains("Unlocked"));
701     long s = lock.writeLock();
702     assertTrue(lock.toString().contains("Write-locked"));
703     lock.unlockWrite(s);
704     s = lock.readLock();
705     assertTrue(lock.toString().contains("Read-locks"));
706     }
707    
708     /**
709 jsr166 1.27 * tryOptimisticRead succeeds and validates if unlocked, fails if
710     * exclusively locked
711 dl 1.4 */
712 jsr166 1.11 public void testValidateOptimistic() throws InterruptedException {
713     StampedLock lock = new StampedLock();
714 jsr166 1.27
715     assertValid(lock, lock.tryOptimisticRead());
716    
717     for (Function<StampedLock, Long> writeLocker : writeLockers()) {
718     long s = assertValid(lock, writeLocker.apply(lock));
719     assertEquals(0L, lock.tryOptimisticRead());
720     releaseWriteLock(lock, s);
721     }
722    
723     for (Function<StampedLock, Long> readLocker : readLockers()) {
724     long s = assertValid(lock, readLocker.apply(lock));
725     long p = assertValid(lock, lock.tryOptimisticRead());
726     releaseReadLock(lock, s);
727     assertTrue(lock.validate(p));
728     }
729    
730     assertValid(lock, lock.tryOptimisticRead());
731 dl 1.4 }
732    
733     /**
734     * tryOptimisticRead stamp does not validate if a write lock intervenes
735     */
736     public void testValidateOptimisticWriteLocked() {
737 jsr166 1.27 final StampedLock lock = new StampedLock();
738     final long p = assertValid(lock, lock.tryOptimisticRead());
739     final long s = assertValid(lock, lock.writeLock());
740 dl 1.4 assertFalse(lock.validate(p));
741 jsr166 1.27 assertEquals(0L, lock.tryOptimisticRead());
742 dl 1.4 assertTrue(lock.validate(s));
743     lock.unlockWrite(s);
744     }
745    
746     /**
747     * tryOptimisticRead stamp does not validate if a write lock
748     * intervenes in another thread
749     */
750 jsr166 1.11 public void testValidateOptimisticWriteLocked2()
751     throws InterruptedException {
752 jsr166 1.32 final CountDownLatch locked = new CountDownLatch(1);
753 dl 1.4 final StampedLock lock = new StampedLock();
754 jsr166 1.27 final long p = assertValid(lock, lock.tryOptimisticRead());
755    
756 dl 1.4 Thread t = newStartedThread(new CheckedInterruptedRunnable() {
757 jsr166 1.11 public void realRun() throws InterruptedException {
758     lock.writeLockInterruptibly();
759 jsr166 1.32 locked.countDown();
760 jsr166 1.11 lock.writeLockInterruptibly();
761     }});
762 jsr166 1.12
763 jsr166 1.34 await(locked);
764 jsr166 1.11 assertFalse(lock.validate(p));
765 jsr166 1.27 assertEquals(0L, lock.tryOptimisticRead());
766 jsr166 1.35 assertThreadBlocks(t, Thread.State.WAITING);
767 jsr166 1.11 t.interrupt();
768     awaitTermination(t);
769 jsr166 1.33 assertTrue(lock.isWriteLocked());
770 dl 1.4 }
771    
772     /**
773 jsr166 1.27 * tryConvertToOptimisticRead succeeds and validates if successfully locked
774 dl 1.4 */
775 jsr166 1.11 public void testTryConvertToOptimisticRead() throws InterruptedException {
776     StampedLock lock = new StampedLock();
777 jsr166 1.27 long s, p, q;
778 jsr166 1.19 assertEquals(0L, lock.tryConvertToOptimisticRead(0L));
779    
780 jsr166 1.27 s = assertValid(lock, lock.tryOptimisticRead());
781 jsr166 1.19 assertEquals(s, lock.tryConvertToOptimisticRead(s));
782     assertTrue(lock.validate(s));
783    
784 jsr166 1.27 for (Function<StampedLock, Long> writeLocker : writeLockers()) {
785     s = assertValid(lock, writeLocker.apply(lock));
786     p = assertValid(lock, lock.tryConvertToOptimisticRead(s));
787     assertFalse(lock.validate(s));
788     assertTrue(lock.validate(p));
789     assertUnlocked(lock);
790     }
791 jsr166 1.20
792 jsr166 1.27 for (Function<StampedLock, Long> readLocker : readLockers()) {
793     s = assertValid(lock, readLocker.apply(lock));
794     q = assertValid(lock, lock.tryOptimisticRead());
795     assertEquals(q, lock.tryConvertToOptimisticRead(q));
796     assertTrue(lock.validate(q));
797     assertTrue(lock.isReadLocked());
798     p = assertValid(lock, lock.tryConvertToOptimisticRead(s));
799     assertTrue(lock.validate(p));
800     assertTrue(lock.validate(s));
801     assertUnlocked(lock);
802     assertEquals(q, lock.tryConvertToOptimisticRead(q));
803     assertTrue(lock.validate(q));
804     }
805 dl 1.4 }
806    
807     /**
808 jsr166 1.27 * tryConvertToReadLock succeeds for valid stamps
809 dl 1.4 */
810 jsr166 1.11 public void testTryConvertToReadLock() throws InterruptedException {
811     StampedLock lock = new StampedLock();
812     long s, p;
813 jsr166 1.22
814 jsr166 1.27 assertEquals(0L, lock.tryConvertToReadLock(0L));
815 jsr166 1.22
816 jsr166 1.27 s = assertValid(lock, lock.tryOptimisticRead());
817     p = assertValid(lock, lock.tryConvertToReadLock(s));
818 jsr166 1.22 assertTrue(lock.isReadLocked());
819     assertEquals(1, lock.getReadLockCount());
820 jsr166 1.27 assertTrue(lock.validate(s));
821 jsr166 1.11 lock.unlockRead(p);
822 jsr166 1.22
823 jsr166 1.27 s = assertValid(lock, lock.tryOptimisticRead());
824 jsr166 1.24 lock.readLock();
825 jsr166 1.27 p = assertValid(lock, lock.tryConvertToReadLock(s));
826 jsr166 1.24 assertTrue(lock.isReadLocked());
827     assertEquals(2, lock.getReadLockCount());
828     lock.unlockRead(p);
829     lock.unlockRead(p);
830 jsr166 1.27 assertUnlocked(lock);
831 jsr166 1.24
832 jsr166 1.27 for (BiConsumer<StampedLock, Long> readUnlocker : readUnlockers()) {
833     for (Function<StampedLock, Long> writeLocker : writeLockers()) {
834     s = assertValid(lock, writeLocker.apply(lock));
835     p = assertValid(lock, lock.tryConvertToReadLock(s));
836     assertFalse(lock.validate(s));
837     assertTrue(lock.isReadLocked());
838     assertEquals(1, lock.getReadLockCount());
839     readUnlocker.accept(lock, p);
840     }
841    
842     for (Function<StampedLock, Long> readLocker : readLockers()) {
843     s = assertValid(lock, readLocker.apply(lock));
844     assertEquals(s, lock.tryConvertToReadLock(s));
845     assertTrue(lock.validate(s));
846     assertTrue(lock.isReadLocked());
847     assertEquals(1, lock.getReadLockCount());
848     readUnlocker.accept(lock, s);
849     }
850     }
851 dl 1.4 }
852    
853     /**
854 jsr166 1.27 * tryConvertToWriteLock succeeds if lock available; fails if multiply read locked
855 dl 1.4 */
856 jsr166 1.11 public void testTryConvertToWriteLock() throws InterruptedException {
857     StampedLock lock = new StampedLock();
858     long s, p;
859 jsr166 1.21
860 jsr166 1.27 assertEquals(0L, lock.tryConvertToWriteLock(0L));
861 jsr166 1.21
862 jsr166 1.11 assertTrue((s = lock.tryOptimisticRead()) != 0L);
863     assertTrue((p = lock.tryConvertToWriteLock(s)) != 0L);
864 jsr166 1.23 assertTrue(lock.isWriteLocked());
865 jsr166 1.11 lock.unlockWrite(p);
866 jsr166 1.21
867 jsr166 1.27 for (BiConsumer<StampedLock, Long> writeUnlocker : writeUnlockers()) {
868     for (Function<StampedLock, Long> writeLocker : writeLockers()) {
869     s = assertValid(lock, writeLocker.apply(lock));
870     assertEquals(s, lock.tryConvertToWriteLock(s));
871     assertTrue(lock.validate(s));
872     assertTrue(lock.isWriteLocked());
873     writeUnlocker.accept(lock, s);
874     }
875    
876     for (Function<StampedLock, Long> readLocker : readLockers()) {
877     s = assertValid(lock, readLocker.apply(lock));
878     p = assertValid(lock, lock.tryConvertToWriteLock(s));
879     assertFalse(lock.validate(s));
880     assertTrue(lock.validate(p));
881     assertTrue(lock.isWriteLocked());
882     writeUnlocker.accept(lock, p);
883     }
884     }
885 jsr166 1.21
886 jsr166 1.27 // failure if multiply read locked
887     for (Function<StampedLock, Long> readLocker : readLockers()) {
888     s = assertValid(lock, readLocker.apply(lock));
889     p = assertValid(lock, readLocker.apply(lock));
890     assertEquals(0L, lock.tryConvertToWriteLock(s));
891     assertTrue(lock.validate(s));
892     assertTrue(lock.validate(p));
893     assertEquals(2, lock.getReadLockCount());
894     lock.unlock(p);
895     lock.unlock(s);
896     assertUnlocked(lock);
897     }
898 dl 1.4 }
899    
900     /**
901     * asWriteLock can be locked and unlocked
902     */
903 jsr166 1.27 public void testAsWriteLock() throws Throwable {
904 dl 1.4 StampedLock sl = new StampedLock();
905     Lock lock = sl.asWriteLock();
906 jsr166 1.27 for (Action locker : lockLockers(lock)) {
907     locker.run();
908     assertTrue(sl.isWriteLocked());
909     assertFalse(sl.isReadLocked());
910     assertFalse(lock.tryLock());
911     lock.unlock();
912     assertUnlocked(sl);
913     }
914 dl 1.4 }
915    
916     /**
917     * asReadLock can be locked and unlocked
918     */
919 jsr166 1.27 public void testAsReadLock() throws Throwable {
920 dl 1.4 StampedLock sl = new StampedLock();
921     Lock lock = sl.asReadLock();
922 jsr166 1.27 for (Action locker : lockLockers(lock)) {
923     locker.run();
924     assertTrue(sl.isReadLocked());
925     assertFalse(sl.isWriteLocked());
926     assertEquals(1, sl.getReadLockCount());
927     locker.run();
928     assertTrue(sl.isReadLocked());
929     assertEquals(2, sl.getReadLockCount());
930     lock.unlock();
931     lock.unlock();
932     assertUnlocked(sl);
933     }
934 dl 1.4 }
935    
936     /**
937     * asReadWriteLock.writeLock can be locked and unlocked
938     */
939 jsr166 1.27 public void testAsReadWriteLockWriteLock() throws Throwable {
940 dl 1.4 StampedLock sl = new StampedLock();
941     Lock lock = sl.asReadWriteLock().writeLock();
942 jsr166 1.27 for (Action locker : lockLockers(lock)) {
943     locker.run();
944     assertTrue(sl.isWriteLocked());
945     assertFalse(sl.isReadLocked());
946     assertFalse(lock.tryLock());
947     lock.unlock();
948     assertUnlocked(sl);
949     }
950 dl 1.4 }
951    
952     /**
953     * asReadWriteLock.readLock can be locked and unlocked
954     */
955 jsr166 1.27 public void testAsReadWriteLockReadLock() throws Throwable {
956 dl 1.4 StampedLock sl = new StampedLock();
957     Lock lock = sl.asReadWriteLock().readLock();
958 jsr166 1.27 for (Action locker : lockLockers(lock)) {
959     locker.run();
960     assertTrue(sl.isReadLocked());
961     assertFalse(sl.isWriteLocked());
962     assertEquals(1, sl.getReadLockCount());
963     locker.run();
964     assertTrue(sl.isReadLocked());
965     assertEquals(2, sl.getReadLockCount());
966     lock.unlock();
967     lock.unlock();
968     assertUnlocked(sl);
969     }
970 dl 1.4 }
971 jsr166 1.1
972 jsr166 1.15 /**
973     * Lock.newCondition throws UnsupportedOperationException
974     */
975     public void testLockViewsDoNotSupportConditions() {
976     StampedLock sl = new StampedLock();
977     assertThrows(UnsupportedOperationException.class,
978     () -> sl.asWriteLock().newCondition(),
979     () -> sl.asReadLock().newCondition(),
980     () -> sl.asReadWriteLock().writeLock().newCondition(),
981     () -> sl.asReadWriteLock().readLock().newCondition());
982     }
983    
984 jsr166 1.16 /**
985     * Passing optimistic read stamps to unlock operations result in
986     * IllegalMonitorStateException
987     */
988     public void testCannotUnlockOptimisticReadStamps() {
989 jsr166 1.43 {
990     StampedLock sl = new StampedLock();
991     long stamp = assertValid(sl, sl.tryOptimisticRead());
992     assertThrows(IllegalMonitorStateException.class,
993     () -> sl.unlockRead(stamp));
994     }
995     {
996     StampedLock sl = new StampedLock();
997     long stamp = sl.tryOptimisticRead();
998     assertThrows(IllegalMonitorStateException.class,
999     () -> sl.unlock(stamp));
1000     }
1001    
1002     {
1003     StampedLock sl = new StampedLock();
1004     long stamp = sl.tryOptimisticRead();
1005     sl.writeLock();
1006     assertThrows(IllegalMonitorStateException.class,
1007     () -> sl.unlock(stamp));
1008     }
1009     {
1010     StampedLock sl = new StampedLock();
1011     sl.readLock();
1012     long stamp = assertValid(sl, sl.tryOptimisticRead());
1013     assertThrows(IllegalMonitorStateException.class,
1014     () -> sl.unlockRead(stamp));
1015     }
1016     {
1017     StampedLock sl = new StampedLock();
1018     sl.readLock();
1019     long stamp = assertValid(sl, sl.tryOptimisticRead());
1020     assertThrows(IllegalMonitorStateException.class,
1021     () -> sl.unlock(stamp));
1022     }
1023 jsr166 1.16
1024 jsr166 1.43 {
1025     StampedLock sl = new StampedLock();
1026     long stamp = sl.tryConvertToOptimisticRead(sl.writeLock());
1027     assertValid(sl, stamp);
1028     sl.writeLock();
1029     assertThrows(IllegalMonitorStateException.class,
1030     () -> sl.unlockWrite(stamp));
1031     }
1032     {
1033     StampedLock sl = new StampedLock();
1034     long stamp = sl.tryConvertToOptimisticRead(sl.writeLock());
1035     sl.writeLock();
1036     assertThrows(IllegalMonitorStateException.class,
1037     () -> sl.unlock(stamp));
1038     }
1039     {
1040     StampedLock sl = new StampedLock();
1041     long stamp = sl.tryConvertToOptimisticRead(sl.writeLock());
1042     sl.readLock();
1043     assertThrows(IllegalMonitorStateException.class,
1044     () -> sl.unlockRead(stamp));
1045     }
1046     {
1047     StampedLock sl = new StampedLock();
1048     long stamp = sl.tryConvertToOptimisticRead(sl.writeLock());
1049     sl.readLock();
1050     assertThrows(IllegalMonitorStateException.class,
1051     () -> sl.unlock(stamp));
1052     }
1053 jsr166 1.17
1054 jsr166 1.43 {
1055     StampedLock sl = new StampedLock();
1056     long stamp = sl.tryConvertToOptimisticRead(sl.readLock());
1057     assertValid(sl, stamp);
1058     sl.writeLock();
1059     assertThrows(IllegalMonitorStateException.class,
1060     () -> sl.unlockWrite(stamp));
1061     }
1062     {
1063     StampedLock sl = new StampedLock();
1064     long stamp = sl.tryConvertToOptimisticRead(sl.readLock());
1065     sl.writeLock();
1066     assertThrows(IllegalMonitorStateException.class,
1067     () -> sl.unlock(stamp));
1068     }
1069     {
1070     StampedLock sl = new StampedLock();
1071     long stamp = sl.tryConvertToOptimisticRead(sl.readLock());
1072     sl.readLock();
1073     assertThrows(IllegalMonitorStateException.class,
1074     () -> sl.unlockRead(stamp));
1075     }
1076     {
1077     StampedLock sl = new StampedLock();
1078     sl.readLock();
1079     long stamp = sl.tryConvertToOptimisticRead(sl.readLock());
1080     assertValid(sl, stamp);
1081     sl.readLock();
1082     assertThrows(IllegalMonitorStateException.class,
1083     () -> sl.unlockRead(stamp));
1084     }
1085     {
1086     StampedLock sl = new StampedLock();
1087     long stamp = sl.tryConvertToOptimisticRead(sl.readLock());
1088     sl.readLock();
1089     assertThrows(IllegalMonitorStateException.class,
1090     () -> sl.unlock(stamp));
1091     }
1092     {
1093     StampedLock sl = new StampedLock();
1094     sl.readLock();
1095     long stamp = sl.tryConvertToOptimisticRead(sl.readLock());
1096     sl.readLock();
1097     assertThrows(IllegalMonitorStateException.class,
1098     () -> sl.unlock(stamp));
1099     }
1100 jsr166 1.16 }
1101    
1102 jsr166 1.25 static long writeLockInterruptiblyUninterrupted(StampedLock sl) {
1103     try { return sl.writeLockInterruptibly(); }
1104     catch (InterruptedException ex) { throw new AssertionError(ex); }
1105     }
1106    
1107     static long tryWriteLockUninterrupted(StampedLock sl, long time, TimeUnit unit) {
1108     try { return sl.tryWriteLock(time, unit); }
1109     catch (InterruptedException ex) { throw new AssertionError(ex); }
1110     }
1111    
1112 jsr166 1.26 static long readLockInterruptiblyUninterrupted(StampedLock sl) {
1113     try { return sl.readLockInterruptibly(); }
1114     catch (InterruptedException ex) { throw new AssertionError(ex); }
1115     }
1116    
1117     static long tryReadLockUninterrupted(StampedLock sl, long time, TimeUnit unit) {
1118     try { return sl.tryReadLock(time, unit); }
1119     catch (InterruptedException ex) { throw new AssertionError(ex); }
1120     }
1121    
1122 jsr166 1.25 /**
1123 jsr166 1.27 * Invalid stamps result in IllegalMonitorStateException
1124 jsr166 1.25 */
1125 jsr166 1.27 public void testInvalidStampsThrowIllegalMonitorStateException() {
1126     final StampedLock sl = new StampedLock();
1127    
1128     assertThrows(IllegalMonitorStateException.class,
1129     () -> sl.unlockWrite(0L),
1130     () -> sl.unlockRead(0L),
1131     () -> sl.unlock(0L));
1132    
1133     final long optimisticStamp = sl.tryOptimisticRead();
1134     final long readStamp = sl.readLock();
1135     sl.unlockRead(readStamp);
1136     final long writeStamp = sl.writeLock();
1137     sl.unlockWrite(writeStamp);
1138     assertTrue(optimisticStamp != 0L && readStamp != 0L && writeStamp != 0L);
1139     final long[] noLongerValidStamps = { optimisticStamp, readStamp, writeStamp };
1140     final Runnable assertNoLongerValidStampsThrow = () -> {
1141     for (long noLongerValidStamp : noLongerValidStamps)
1142     assertThrows(IllegalMonitorStateException.class,
1143     () -> sl.unlockWrite(noLongerValidStamp),
1144     () -> sl.unlockRead(noLongerValidStamp),
1145     () -> sl.unlock(noLongerValidStamp));
1146     };
1147     assertNoLongerValidStampsThrow.run();
1148 jsr166 1.25
1149 jsr166 1.27 for (Function<StampedLock, Long> readLocker : readLockers())
1150     for (BiConsumer<StampedLock, Long> readUnlocker : readUnlockers()) {
1151     final long stamp = readLocker.apply(sl);
1152     assertValid(sl, stamp);
1153     assertNoLongerValidStampsThrow.run();
1154     assertThrows(IllegalMonitorStateException.class,
1155     () -> sl.unlockWrite(stamp),
1156     () -> sl.unlockRead(sl.tryOptimisticRead()),
1157     () -> sl.unlockRead(0L));
1158     readUnlocker.accept(sl, stamp);
1159     assertUnlocked(sl);
1160     assertNoLongerValidStampsThrow.run();
1161     }
1162 jsr166 1.26
1163 jsr166 1.27 for (Function<StampedLock, Long> writeLocker : writeLockers())
1164     for (BiConsumer<StampedLock, Long> writeUnlocker : writeUnlockers()) {
1165 jsr166 1.26 final long stamp = writeLocker.apply(sl);
1166 jsr166 1.27 assertValid(sl, stamp);
1167     assertNoLongerValidStampsThrow.run();
1168 jsr166 1.26 assertThrows(IllegalMonitorStateException.class,
1169 jsr166 1.27 () -> sl.unlockRead(stamp),
1170     () -> sl.unlockWrite(0L));
1171 jsr166 1.26 writeUnlocker.accept(sl, stamp);
1172 jsr166 1.27 assertUnlocked(sl);
1173     assertNoLongerValidStampsThrow.run();
1174 jsr166 1.26 }
1175     }
1176    
1177     /**
1178 jsr166 1.27 * Read locks can be very deeply nested
1179 jsr166 1.26 */
1180 jsr166 1.27 public void testDeeplyNestedReadLocks() {
1181     final StampedLock lock = new StampedLock();
1182     final int depth = 300;
1183     final long[] stamps = new long[depth];
1184     final List<Function<StampedLock, Long>> readLockers = readLockers();
1185     final List<BiConsumer<StampedLock, Long>> readUnlockers = readUnlockers();
1186     for (int i = 0; i < depth; i++) {
1187     Function<StampedLock, Long> readLocker
1188     = readLockers.get(i % readLockers.size());
1189     long stamp = readLocker.apply(lock);
1190     assertEquals(i + 1, lock.getReadLockCount());
1191     assertTrue(lock.isReadLocked());
1192     stamps[i] = stamp;
1193     }
1194     for (int i = 0; i < depth; i++) {
1195     BiConsumer<StampedLock, Long> readUnlocker
1196     = readUnlockers.get(i % readUnlockers.size());
1197     assertEquals(depth - i, lock.getReadLockCount());
1198     assertTrue(lock.isReadLocked());
1199     readUnlocker.accept(lock, stamps[depth - 1 - i]);
1200 jsr166 1.25 }
1201 jsr166 1.27 assertUnlocked(lock);
1202 jsr166 1.25 }
1203 jsr166 1.38
1204     /**
1205     * Stamped locks are not reentrant.
1206     */
1207     public void testNonReentrant() throws InterruptedException {
1208     final StampedLock lock = new StampedLock();
1209     long stamp;
1210    
1211     stamp = lock.writeLock();
1212     assertValid(lock, stamp);
1213     assertEquals(0L, lock.tryWriteLock(0L, DAYS));
1214     assertEquals(0L, lock.tryReadLock(0L, DAYS));
1215     assertValid(lock, stamp);
1216     lock.unlockWrite(stamp);
1217    
1218     stamp = lock.tryWriteLock(1L, DAYS);
1219     assertEquals(0L, lock.tryWriteLock(0L, DAYS));
1220     assertValid(lock, stamp);
1221     lock.unlockWrite(stamp);
1222    
1223     stamp = lock.readLock();
1224     assertEquals(0L, lock.tryWriteLock(0L, DAYS));
1225     assertValid(lock, stamp);
1226     lock.unlockRead(stamp);
1227     }
1228    
1229     /**
1230     * """StampedLocks have no notion of ownership. Locks acquired in
1231     * one thread can be released or converted in another."""
1232     */
1233     public void testNoOwnership() throws Throwable {
1234     ArrayList<Future<?>> futures = new ArrayList<>();
1235     for (Function<StampedLock, Long> writeLocker : writeLockers())
1236     for (BiConsumer<StampedLock, Long> writeUnlocker : writeUnlockers()) {
1237     StampedLock lock = new StampedLock();
1238     long stamp = writeLocker.apply(lock);
1239     futures.add(cachedThreadPool.submit(new CheckedRunnable() {
1240     public void realRun() {
1241     writeUnlocker.accept(lock, stamp);
1242     assertUnlocked(lock);
1243     assertFalse(lock.validate(stamp));
1244     }}));
1245     }
1246     for (Future<?> future : futures)
1247     assertNull(future.get());
1248     }
1249 jsr166 1.39
1250     /** Tries out sample usage code from StampedLock javadoc. */
1251     public void testSampleUsage() throws Throwable {
1252     class Point {
1253     private double x, y;
1254     private final StampedLock sl = new StampedLock();
1255    
1256     void move(double deltaX, double deltaY) { // an exclusively locked method
1257     long stamp = sl.writeLock();
1258     try {
1259     x += deltaX;
1260     y += deltaY;
1261     } finally {
1262     sl.unlockWrite(stamp);
1263     }
1264     }
1265    
1266     double distanceFromOrigin() { // A read-only method
1267     double currentX, currentY;
1268     long stamp = sl.tryOptimisticRead();
1269     do {
1270     if (stamp == 0L)
1271     stamp = sl.readLock();
1272     try {
1273     // possibly racy reads
1274     currentX = x;
1275     currentY = y;
1276     } finally {
1277     stamp = sl.tryConvertToOptimisticRead(stamp);
1278     }
1279     } while (stamp == 0);
1280     return Math.hypot(currentX, currentY);
1281     }
1282 jsr166 1.41
1283     double distanceFromOrigin2() {
1284     long stamp = sl.tryOptimisticRead();
1285     try {
1286     retryHoldingLock:
1287     for (;; stamp = sl.readLock()) {
1288     if (stamp == 0L)
1289     continue retryHoldingLock;
1290     // possibly racy reads
1291     double currentX = x;
1292     double currentY = y;
1293     if (!sl.validate(stamp))
1294     continue retryHoldingLock;
1295     return Math.hypot(currentX, currentY);
1296     }
1297     } finally {
1298     if (StampedLock.isReadLockStamp(stamp))
1299     sl.unlockRead(stamp);
1300     }
1301     }
1302    
1303     void moveIfAtOrigin(double newX, double newY) {
1304     long stamp = sl.readLock();
1305     try {
1306     while (x == 0.0 && y == 0.0) {
1307     long ws = sl.tryConvertToWriteLock(stamp);
1308     if (ws != 0L) {
1309     stamp = ws;
1310     x = newX;
1311     y = newY;
1312     return;
1313     }
1314     else {
1315     sl.unlockRead(stamp);
1316     stamp = sl.writeLock();
1317     }
1318     }
1319     } finally {
1320     sl.unlock(stamp);
1321     }
1322     }
1323 jsr166 1.39 }
1324    
1325     Point p = new Point();
1326     p.move(3.0, 4.0);
1327     assertEquals(5.0, p.distanceFromOrigin());
1328 jsr166 1.41 p.moveIfAtOrigin(5.0, 12.0);
1329     assertEquals(5.0, p.distanceFromOrigin2());
1330     }
1331    
1332     /**
1333     * Stamp inspection methods work as expected, and do not inspect
1334     * the state of the lock itself.
1335     */
1336     public void testStampStateInspectionMethods() {
1337     StampedLock lock = new StampedLock();
1338    
1339     assertFalse(isWriteLockStamp(0L));
1340     assertFalse(isReadLockStamp(0L));
1341     assertFalse(isLockStamp(0L));
1342     assertFalse(isOptimisticReadStamp(0L));
1343    
1344     {
1345     long stamp = lock.writeLock();
1346     for (int i = 0; i < 2; i++) {
1347     assertTrue(isWriteLockStamp(stamp));
1348     assertFalse(isReadLockStamp(stamp));
1349     assertTrue(isLockStamp(stamp));
1350     assertFalse(isOptimisticReadStamp(stamp));
1351     if (i == 0)
1352     lock.unlockWrite(stamp);
1353     }
1354     }
1355    
1356     {
1357     long stamp = lock.readLock();
1358     for (int i = 0; i < 2; i++) {
1359     assertFalse(isWriteLockStamp(stamp));
1360     assertTrue(isReadLockStamp(stamp));
1361     assertTrue(isLockStamp(stamp));
1362     assertFalse(isOptimisticReadStamp(stamp));
1363     if (i == 0)
1364     lock.unlockRead(stamp);
1365     }
1366     }
1367    
1368     {
1369     long optimisticStamp = lock.tryOptimisticRead();
1370     long readStamp = lock.tryConvertToReadLock(optimisticStamp);
1371     long writeStamp = lock.tryConvertToWriteLock(readStamp);
1372     for (int i = 0; i < 2; i++) {
1373     assertFalse(isWriteLockStamp(optimisticStamp));
1374     assertFalse(isReadLockStamp(optimisticStamp));
1375     assertFalse(isLockStamp(optimisticStamp));
1376     assertTrue(isOptimisticReadStamp(optimisticStamp));
1377    
1378     assertFalse(isWriteLockStamp(readStamp));
1379     assertTrue(isReadLockStamp(readStamp));
1380     assertTrue(isLockStamp(readStamp));
1381     assertFalse(isOptimisticReadStamp(readStamp));
1382    
1383     assertTrue(isWriteLockStamp(writeStamp));
1384     assertFalse(isReadLockStamp(writeStamp));
1385     assertTrue(isLockStamp(writeStamp));
1386     assertFalse(isOptimisticReadStamp(writeStamp));
1387     if (i == 0)
1388     lock.unlockWrite(writeStamp);
1389     }
1390     }
1391 jsr166 1.39 }
1392 jsr166 1.40
1393 jsr166 1.44 /**
1394     * Multiple threads repeatedly contend for the same lock.
1395     */
1396     public void testConcurrentAccess() throws Exception {
1397     final StampedLock sl = new StampedLock();
1398     final Lock wl = sl.asWriteLock();
1399     final Lock rl = sl.asReadLock();
1400     final long testDurationMillis = expensiveTests ? 1000 : 2;
1401     final int nTasks = ThreadLocalRandom.current().nextInt(1, 10);
1402     final AtomicBoolean done = new AtomicBoolean(false);
1403     final List<CompletableFuture> futures = new ArrayList<>();
1404     final List<Callable<Long>> stampedWriteLockers = List.of(
1405     () -> sl.writeLock(),
1406     () -> writeLockInterruptiblyUninterrupted(sl),
1407     () -> tryWriteLockUninterrupted(sl, LONG_DELAY_MS, MILLISECONDS),
1408     () -> {
1409     long stamp;
1410     do { stamp = sl.tryConvertToWriteLock(sl.tryOptimisticRead()); }
1411     while (stamp == 0L);
1412     return stamp;
1413     },
1414     () -> {
1415     long stamp;
1416     do { stamp = sl.tryWriteLock(); } while (stamp == 0L);
1417     return stamp;
1418     },
1419     () -> {
1420     long stamp;
1421     do { stamp = sl.tryWriteLock(0L, DAYS); } while (stamp == 0L);
1422     return stamp;
1423     });
1424     final List<Callable<Long>> stampedReadLockers = List.of(
1425     () -> sl.readLock(),
1426     () -> readLockInterruptiblyUninterrupted(sl),
1427     () -> tryReadLockUninterrupted(sl, LONG_DELAY_MS, MILLISECONDS),
1428     () -> {
1429     long stamp;
1430     do { stamp = sl.tryConvertToReadLock(sl.tryOptimisticRead()); }
1431     while (stamp == 0L);
1432     return stamp;
1433     },
1434     () -> {
1435     long stamp;
1436     do { stamp = sl.tryReadLock(); } while (stamp == 0L);
1437     return stamp;
1438     },
1439     () -> {
1440     long stamp;
1441     do { stamp = sl.tryReadLock(0L, DAYS); } while (stamp == 0L);
1442     return stamp;
1443     });
1444     final List<Consumer<Long>> stampedWriteUnlockers = List.of(
1445     stamp -> sl.unlockWrite(stamp),
1446     stamp -> sl.unlock(stamp),
1447     stamp -> assertTrue(sl.tryUnlockWrite()),
1448     stamp -> wl.unlock(),
1449     stamp -> sl.tryConvertToOptimisticRead(stamp));
1450     final List<Consumer<Long>> stampedReadUnlockers = List.of(
1451     stamp -> sl.unlockRead(stamp),
1452     stamp -> sl.unlock(stamp),
1453     stamp -> assertTrue(sl.tryUnlockRead()),
1454     stamp -> rl.unlock(),
1455     stamp -> sl.tryConvertToOptimisticRead(stamp));
1456     final Action writer = () -> {
1457     // repeatedly acquires write lock
1458     var locker = chooseRandomly(stampedWriteLockers);
1459     var unlocker = chooseRandomly(stampedWriteUnlockers);
1460     while (!done.getAcquire()) {
1461     long stamp = locker.call();
1462     try {
1463     assertTrue(isWriteLockStamp(stamp));
1464     assertTrue(sl.isWriteLocked());
1465     assertFalse(isReadLockStamp(stamp));
1466     assertFalse(sl.isReadLocked());
1467     assertEquals(0, sl.getReadLockCount());
1468     assertTrue(sl.validate(stamp));
1469     } finally {
1470     unlocker.accept(stamp);
1471     }
1472     }
1473     };
1474     final Action reader = () -> {
1475     // repeatedly acquires read lock
1476     var locker = chooseRandomly(stampedReadLockers);
1477     var unlocker = chooseRandomly(stampedReadUnlockers);
1478     while (!done.getAcquire()) {
1479     long stamp = locker.call();
1480     try {
1481     assertFalse(isWriteLockStamp(stamp));
1482     assertFalse(sl.isWriteLocked());
1483     assertTrue(isReadLockStamp(stamp));
1484     assertTrue(sl.isReadLocked());
1485     assertTrue(sl.getReadLockCount() > 0);
1486     assertTrue(sl.validate(stamp));
1487     } finally {
1488     unlocker.accept(stamp);
1489     }
1490     }
1491     };
1492     for (int i = nTasks; i--> 0; ) {
1493     Action task = chooseRandomly(writer, reader);
1494     futures.add(CompletableFuture.runAsync(checkedRunnable(task)));
1495     }
1496     Thread.sleep(testDurationMillis);
1497     done.setRelease(true);
1498     for (var future : futures)
1499     checkTimedGet(future, null);
1500     }
1501    
1502 jsr166 1.1 }