ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/test/tck/StampedLockTest.java
Revision: 1.47
Committed: Tue Jan 26 13:33:06 2021 UTC (3 years, 3 months ago) by dl
Branch: MAIN
CVS Tags: HEAD
Changes since 1.46: +1 -1 lines
Log Message:
Replace Integer with Item class

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 jsr166 1.46 releaseReadLock(lock, s);
707 dl 1.4 }
708    
709     /**
710 jsr166 1.27 * tryOptimisticRead succeeds and validates if unlocked, fails if
711     * exclusively locked
712 dl 1.4 */
713 jsr166 1.11 public void testValidateOptimistic() throws InterruptedException {
714     StampedLock lock = new StampedLock();
715 jsr166 1.27
716     assertValid(lock, lock.tryOptimisticRead());
717    
718     for (Function<StampedLock, Long> writeLocker : writeLockers()) {
719     long s = assertValid(lock, writeLocker.apply(lock));
720     assertEquals(0L, lock.tryOptimisticRead());
721     releaseWriteLock(lock, s);
722     }
723    
724     for (Function<StampedLock, Long> readLocker : readLockers()) {
725     long s = assertValid(lock, readLocker.apply(lock));
726     long p = assertValid(lock, lock.tryOptimisticRead());
727     releaseReadLock(lock, s);
728     assertTrue(lock.validate(p));
729     }
730    
731     assertValid(lock, lock.tryOptimisticRead());
732 dl 1.4 }
733    
734     /**
735     * tryOptimisticRead stamp does not validate if a write lock intervenes
736     */
737     public void testValidateOptimisticWriteLocked() {
738 jsr166 1.27 final StampedLock lock = new StampedLock();
739     final long p = assertValid(lock, lock.tryOptimisticRead());
740     final long s = assertValid(lock, lock.writeLock());
741 dl 1.4 assertFalse(lock.validate(p));
742 jsr166 1.27 assertEquals(0L, lock.tryOptimisticRead());
743 dl 1.4 assertTrue(lock.validate(s));
744     lock.unlockWrite(s);
745     }
746    
747     /**
748     * tryOptimisticRead stamp does not validate if a write lock
749     * intervenes in another thread
750     */
751 jsr166 1.11 public void testValidateOptimisticWriteLocked2()
752     throws InterruptedException {
753 jsr166 1.32 final CountDownLatch locked = new CountDownLatch(1);
754 dl 1.4 final StampedLock lock = new StampedLock();
755 jsr166 1.27 final long p = assertValid(lock, lock.tryOptimisticRead());
756    
757 dl 1.4 Thread t = newStartedThread(new CheckedInterruptedRunnable() {
758 jsr166 1.11 public void realRun() throws InterruptedException {
759     lock.writeLockInterruptibly();
760 jsr166 1.32 locked.countDown();
761 jsr166 1.11 lock.writeLockInterruptibly();
762     }});
763 jsr166 1.12
764 jsr166 1.34 await(locked);
765 jsr166 1.11 assertFalse(lock.validate(p));
766 jsr166 1.27 assertEquals(0L, lock.tryOptimisticRead());
767 jsr166 1.35 assertThreadBlocks(t, Thread.State.WAITING);
768 jsr166 1.11 t.interrupt();
769     awaitTermination(t);
770 jsr166 1.33 assertTrue(lock.isWriteLocked());
771 dl 1.4 }
772    
773     /**
774 jsr166 1.27 * tryConvertToOptimisticRead succeeds and validates if successfully locked
775 dl 1.4 */
776 jsr166 1.11 public void testTryConvertToOptimisticRead() throws InterruptedException {
777     StampedLock lock = new StampedLock();
778 jsr166 1.27 long s, p, q;
779 jsr166 1.19 assertEquals(0L, lock.tryConvertToOptimisticRead(0L));
780    
781 jsr166 1.27 s = assertValid(lock, lock.tryOptimisticRead());
782 jsr166 1.19 assertEquals(s, lock.tryConvertToOptimisticRead(s));
783     assertTrue(lock.validate(s));
784    
785 jsr166 1.27 for (Function<StampedLock, Long> writeLocker : writeLockers()) {
786     s = assertValid(lock, writeLocker.apply(lock));
787     p = assertValid(lock, lock.tryConvertToOptimisticRead(s));
788     assertFalse(lock.validate(s));
789     assertTrue(lock.validate(p));
790     assertUnlocked(lock);
791     }
792 jsr166 1.20
793 jsr166 1.27 for (Function<StampedLock, Long> readLocker : readLockers()) {
794     s = assertValid(lock, readLocker.apply(lock));
795     q = assertValid(lock, lock.tryOptimisticRead());
796     assertEquals(q, lock.tryConvertToOptimisticRead(q));
797     assertTrue(lock.validate(q));
798     assertTrue(lock.isReadLocked());
799     p = assertValid(lock, lock.tryConvertToOptimisticRead(s));
800     assertTrue(lock.validate(p));
801     assertTrue(lock.validate(s));
802     assertUnlocked(lock);
803     assertEquals(q, lock.tryConvertToOptimisticRead(q));
804     assertTrue(lock.validate(q));
805     }
806 dl 1.4 }
807    
808     /**
809 jsr166 1.27 * tryConvertToReadLock succeeds for valid stamps
810 dl 1.4 */
811 jsr166 1.11 public void testTryConvertToReadLock() throws InterruptedException {
812     StampedLock lock = new StampedLock();
813     long s, p;
814 jsr166 1.22
815 jsr166 1.27 assertEquals(0L, lock.tryConvertToReadLock(0L));
816 jsr166 1.22
817 jsr166 1.27 s = assertValid(lock, lock.tryOptimisticRead());
818     p = assertValid(lock, lock.tryConvertToReadLock(s));
819 jsr166 1.22 assertTrue(lock.isReadLocked());
820     assertEquals(1, lock.getReadLockCount());
821 jsr166 1.27 assertTrue(lock.validate(s));
822 jsr166 1.11 lock.unlockRead(p);
823 jsr166 1.22
824 jsr166 1.27 s = assertValid(lock, lock.tryOptimisticRead());
825 jsr166 1.24 lock.readLock();
826 jsr166 1.27 p = assertValid(lock, lock.tryConvertToReadLock(s));
827 jsr166 1.24 assertTrue(lock.isReadLocked());
828     assertEquals(2, lock.getReadLockCount());
829     lock.unlockRead(p);
830     lock.unlockRead(p);
831 jsr166 1.27 assertUnlocked(lock);
832 jsr166 1.24
833 jsr166 1.27 for (BiConsumer<StampedLock, Long> readUnlocker : readUnlockers()) {
834     for (Function<StampedLock, Long> writeLocker : writeLockers()) {
835     s = assertValid(lock, writeLocker.apply(lock));
836     p = assertValid(lock, lock.tryConvertToReadLock(s));
837     assertFalse(lock.validate(s));
838     assertTrue(lock.isReadLocked());
839     assertEquals(1, lock.getReadLockCount());
840     readUnlocker.accept(lock, p);
841     }
842    
843     for (Function<StampedLock, Long> readLocker : readLockers()) {
844     s = assertValid(lock, readLocker.apply(lock));
845     assertEquals(s, lock.tryConvertToReadLock(s));
846     assertTrue(lock.validate(s));
847     assertTrue(lock.isReadLocked());
848     assertEquals(1, lock.getReadLockCount());
849     readUnlocker.accept(lock, s);
850     }
851     }
852 dl 1.4 }
853    
854     /**
855 jsr166 1.27 * tryConvertToWriteLock succeeds if lock available; fails if multiply read locked
856 dl 1.4 */
857 jsr166 1.11 public void testTryConvertToWriteLock() throws InterruptedException {
858     StampedLock lock = new StampedLock();
859     long s, p;
860 jsr166 1.21
861 jsr166 1.27 assertEquals(0L, lock.tryConvertToWriteLock(0L));
862 jsr166 1.21
863 jsr166 1.11 assertTrue((s = lock.tryOptimisticRead()) != 0L);
864     assertTrue((p = lock.tryConvertToWriteLock(s)) != 0L);
865 jsr166 1.23 assertTrue(lock.isWriteLocked());
866 jsr166 1.11 lock.unlockWrite(p);
867 jsr166 1.21
868 jsr166 1.27 for (BiConsumer<StampedLock, Long> writeUnlocker : writeUnlockers()) {
869     for (Function<StampedLock, Long> writeLocker : writeLockers()) {
870     s = assertValid(lock, writeLocker.apply(lock));
871     assertEquals(s, lock.tryConvertToWriteLock(s));
872     assertTrue(lock.validate(s));
873     assertTrue(lock.isWriteLocked());
874     writeUnlocker.accept(lock, s);
875     }
876    
877     for (Function<StampedLock, Long> readLocker : readLockers()) {
878     s = assertValid(lock, readLocker.apply(lock));
879     p = assertValid(lock, lock.tryConvertToWriteLock(s));
880     assertFalse(lock.validate(s));
881     assertTrue(lock.validate(p));
882     assertTrue(lock.isWriteLocked());
883     writeUnlocker.accept(lock, p);
884     }
885     }
886 jsr166 1.21
887 jsr166 1.27 // failure if multiply read locked
888     for (Function<StampedLock, Long> readLocker : readLockers()) {
889     s = assertValid(lock, readLocker.apply(lock));
890     p = assertValid(lock, readLocker.apply(lock));
891     assertEquals(0L, lock.tryConvertToWriteLock(s));
892     assertTrue(lock.validate(s));
893     assertTrue(lock.validate(p));
894     assertEquals(2, lock.getReadLockCount());
895     lock.unlock(p);
896     lock.unlock(s);
897     assertUnlocked(lock);
898     }
899 dl 1.4 }
900    
901     /**
902     * asWriteLock can be locked and unlocked
903     */
904 jsr166 1.27 public void testAsWriteLock() throws Throwable {
905 dl 1.4 StampedLock sl = new StampedLock();
906     Lock lock = sl.asWriteLock();
907 jsr166 1.27 for (Action locker : lockLockers(lock)) {
908     locker.run();
909     assertTrue(sl.isWriteLocked());
910     assertFalse(sl.isReadLocked());
911     assertFalse(lock.tryLock());
912     lock.unlock();
913     assertUnlocked(sl);
914     }
915 dl 1.4 }
916    
917     /**
918     * asReadLock can be locked and unlocked
919     */
920 jsr166 1.27 public void testAsReadLock() throws Throwable {
921 dl 1.4 StampedLock sl = new StampedLock();
922     Lock lock = sl.asReadLock();
923 jsr166 1.27 for (Action locker : lockLockers(lock)) {
924     locker.run();
925     assertTrue(sl.isReadLocked());
926     assertFalse(sl.isWriteLocked());
927     assertEquals(1, sl.getReadLockCount());
928     locker.run();
929     assertTrue(sl.isReadLocked());
930     assertEquals(2, sl.getReadLockCount());
931     lock.unlock();
932     lock.unlock();
933     assertUnlocked(sl);
934     }
935 dl 1.4 }
936    
937     /**
938     * asReadWriteLock.writeLock can be locked and unlocked
939     */
940 jsr166 1.27 public void testAsReadWriteLockWriteLock() throws Throwable {
941 dl 1.4 StampedLock sl = new StampedLock();
942     Lock lock = sl.asReadWriteLock().writeLock();
943 jsr166 1.27 for (Action locker : lockLockers(lock)) {
944     locker.run();
945     assertTrue(sl.isWriteLocked());
946     assertFalse(sl.isReadLocked());
947     assertFalse(lock.tryLock());
948     lock.unlock();
949     assertUnlocked(sl);
950     }
951 dl 1.4 }
952    
953     /**
954     * asReadWriteLock.readLock can be locked and unlocked
955     */
956 jsr166 1.27 public void testAsReadWriteLockReadLock() throws Throwable {
957 dl 1.4 StampedLock sl = new StampedLock();
958     Lock lock = sl.asReadWriteLock().readLock();
959 jsr166 1.27 for (Action locker : lockLockers(lock)) {
960     locker.run();
961     assertTrue(sl.isReadLocked());
962     assertFalse(sl.isWriteLocked());
963     assertEquals(1, sl.getReadLockCount());
964     locker.run();
965     assertTrue(sl.isReadLocked());
966     assertEquals(2, sl.getReadLockCount());
967     lock.unlock();
968     lock.unlock();
969     assertUnlocked(sl);
970     }
971 dl 1.4 }
972 jsr166 1.1
973 jsr166 1.15 /**
974     * Lock.newCondition throws UnsupportedOperationException
975     */
976     public void testLockViewsDoNotSupportConditions() {
977     StampedLock sl = new StampedLock();
978     assertThrows(UnsupportedOperationException.class,
979     () -> sl.asWriteLock().newCondition(),
980     () -> sl.asReadLock().newCondition(),
981     () -> sl.asReadWriteLock().writeLock().newCondition(),
982     () -> sl.asReadWriteLock().readLock().newCondition());
983     }
984    
985 jsr166 1.16 /**
986     * Passing optimistic read stamps to unlock operations result in
987     * IllegalMonitorStateException
988     */
989     public void testCannotUnlockOptimisticReadStamps() {
990 jsr166 1.43 {
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.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 jsr166 1.16
1025 jsr166 1.43 {
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 jsr166 1.17
1055 jsr166 1.43 {
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 jsr166 1.16 }
1102    
1103 jsr166 1.25 static long writeLockInterruptiblyUninterrupted(StampedLock sl) {
1104     try { return sl.writeLockInterruptibly(); }
1105     catch (InterruptedException ex) { throw new AssertionError(ex); }
1106     }
1107    
1108     static long tryWriteLockUninterrupted(StampedLock sl, long time, TimeUnit unit) {
1109     try { return sl.tryWriteLock(time, unit); }
1110     catch (InterruptedException ex) { throw new AssertionError(ex); }
1111     }
1112    
1113 jsr166 1.26 static long readLockInterruptiblyUninterrupted(StampedLock sl) {
1114     try { return sl.readLockInterruptibly(); }
1115     catch (InterruptedException ex) { throw new AssertionError(ex); }
1116     }
1117    
1118     static long tryReadLockUninterrupted(StampedLock sl, long time, TimeUnit unit) {
1119     try { return sl.tryReadLock(time, unit); }
1120     catch (InterruptedException ex) { throw new AssertionError(ex); }
1121     }
1122    
1123 jsr166 1.25 /**
1124 jsr166 1.27 * Invalid stamps result in IllegalMonitorStateException
1125 jsr166 1.25 */
1126 jsr166 1.27 public void testInvalidStampsThrowIllegalMonitorStateException() {
1127     final StampedLock sl = new StampedLock();
1128    
1129     assertThrows(IllegalMonitorStateException.class,
1130     () -> sl.unlockWrite(0L),
1131     () -> sl.unlockRead(0L),
1132     () -> sl.unlock(0L));
1133    
1134     final long optimisticStamp = sl.tryOptimisticRead();
1135     final long readStamp = sl.readLock();
1136     sl.unlockRead(readStamp);
1137     final long writeStamp = sl.writeLock();
1138     sl.unlockWrite(writeStamp);
1139     assertTrue(optimisticStamp != 0L && readStamp != 0L && writeStamp != 0L);
1140     final long[] noLongerValidStamps = { optimisticStamp, readStamp, writeStamp };
1141     final Runnable assertNoLongerValidStampsThrow = () -> {
1142     for (long noLongerValidStamp : noLongerValidStamps)
1143     assertThrows(IllegalMonitorStateException.class,
1144     () -> sl.unlockWrite(noLongerValidStamp),
1145     () -> sl.unlockRead(noLongerValidStamp),
1146     () -> sl.unlock(noLongerValidStamp));
1147     };
1148     assertNoLongerValidStampsThrow.run();
1149 jsr166 1.25
1150 jsr166 1.27 for (Function<StampedLock, Long> readLocker : readLockers())
1151     for (BiConsumer<StampedLock, Long> readUnlocker : readUnlockers()) {
1152     final long stamp = readLocker.apply(sl);
1153     assertValid(sl, stamp);
1154     assertNoLongerValidStampsThrow.run();
1155     assertThrows(IllegalMonitorStateException.class,
1156     () -> sl.unlockWrite(stamp),
1157     () -> sl.unlockRead(sl.tryOptimisticRead()),
1158     () -> sl.unlockRead(0L));
1159     readUnlocker.accept(sl, stamp);
1160     assertUnlocked(sl);
1161     assertNoLongerValidStampsThrow.run();
1162     }
1163 jsr166 1.26
1164 jsr166 1.27 for (Function<StampedLock, Long> writeLocker : writeLockers())
1165     for (BiConsumer<StampedLock, Long> writeUnlocker : writeUnlockers()) {
1166 jsr166 1.26 final long stamp = writeLocker.apply(sl);
1167 jsr166 1.27 assertValid(sl, stamp);
1168     assertNoLongerValidStampsThrow.run();
1169 jsr166 1.26 assertThrows(IllegalMonitorStateException.class,
1170 jsr166 1.27 () -> sl.unlockRead(stamp),
1171     () -> sl.unlockWrite(0L));
1172 jsr166 1.26 writeUnlocker.accept(sl, stamp);
1173 jsr166 1.27 assertUnlocked(sl);
1174     assertNoLongerValidStampsThrow.run();
1175 jsr166 1.26 }
1176     }
1177    
1178     /**
1179 jsr166 1.27 * Read locks can be very deeply nested
1180 jsr166 1.26 */
1181 jsr166 1.27 public void testDeeplyNestedReadLocks() {
1182     final StampedLock lock = new StampedLock();
1183     final int depth = 300;
1184     final long[] stamps = new long[depth];
1185     final List<Function<StampedLock, Long>> readLockers = readLockers();
1186     final List<BiConsumer<StampedLock, Long>> readUnlockers = readUnlockers();
1187     for (int i = 0; i < depth; i++) {
1188     Function<StampedLock, Long> readLocker
1189     = readLockers.get(i % readLockers.size());
1190     long stamp = readLocker.apply(lock);
1191     assertEquals(i + 1, lock.getReadLockCount());
1192     assertTrue(lock.isReadLocked());
1193     stamps[i] = stamp;
1194     }
1195     for (int i = 0; i < depth; i++) {
1196     BiConsumer<StampedLock, Long> readUnlocker
1197     = readUnlockers.get(i % readUnlockers.size());
1198     assertEquals(depth - i, lock.getReadLockCount());
1199     assertTrue(lock.isReadLocked());
1200     readUnlocker.accept(lock, stamps[depth - 1 - i]);
1201 jsr166 1.25 }
1202 jsr166 1.27 assertUnlocked(lock);
1203 jsr166 1.25 }
1204 jsr166 1.38
1205     /**
1206     * Stamped locks are not reentrant.
1207     */
1208     public void testNonReentrant() throws InterruptedException {
1209     final StampedLock lock = new StampedLock();
1210     long stamp;
1211    
1212     stamp = lock.writeLock();
1213     assertValid(lock, stamp);
1214     assertEquals(0L, lock.tryWriteLock(0L, DAYS));
1215     assertEquals(0L, lock.tryReadLock(0L, DAYS));
1216     assertValid(lock, stamp);
1217     lock.unlockWrite(stamp);
1218    
1219     stamp = lock.tryWriteLock(1L, DAYS);
1220     assertEquals(0L, lock.tryWriteLock(0L, DAYS));
1221     assertValid(lock, stamp);
1222     lock.unlockWrite(stamp);
1223    
1224     stamp = lock.readLock();
1225     assertEquals(0L, lock.tryWriteLock(0L, DAYS));
1226     assertValid(lock, stamp);
1227     lock.unlockRead(stamp);
1228     }
1229    
1230     /**
1231     * """StampedLocks have no notion of ownership. Locks acquired in
1232     * one thread can be released or converted in another."""
1233     */
1234     public void testNoOwnership() throws Throwable {
1235     ArrayList<Future<?>> futures = new ArrayList<>();
1236     for (Function<StampedLock, Long> writeLocker : writeLockers())
1237     for (BiConsumer<StampedLock, Long> writeUnlocker : writeUnlockers()) {
1238     StampedLock lock = new StampedLock();
1239     long stamp = writeLocker.apply(lock);
1240     futures.add(cachedThreadPool.submit(new CheckedRunnable() {
1241     public void realRun() {
1242     writeUnlocker.accept(lock, stamp);
1243     assertUnlocked(lock);
1244     assertFalse(lock.validate(stamp));
1245     }}));
1246     }
1247     for (Future<?> future : futures)
1248     assertNull(future.get());
1249     }
1250 jsr166 1.39
1251     /** Tries out sample usage code from StampedLock javadoc. */
1252     public void testSampleUsage() throws Throwable {
1253     class Point {
1254     private double x, y;
1255     private final StampedLock sl = new StampedLock();
1256    
1257     void move(double deltaX, double deltaY) { // an exclusively locked method
1258     long stamp = sl.writeLock();
1259     try {
1260     x += deltaX;
1261     y += deltaY;
1262     } finally {
1263     sl.unlockWrite(stamp);
1264     }
1265     }
1266    
1267     double distanceFromOrigin() { // A read-only method
1268     double currentX, currentY;
1269     long stamp = sl.tryOptimisticRead();
1270     do {
1271     if (stamp == 0L)
1272     stamp = sl.readLock();
1273     try {
1274     // possibly racy reads
1275     currentX = x;
1276     currentY = y;
1277     } finally {
1278     stamp = sl.tryConvertToOptimisticRead(stamp);
1279     }
1280     } while (stamp == 0);
1281     return Math.hypot(currentX, currentY);
1282     }
1283 jsr166 1.41
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 jsr166 1.39 }
1325    
1326     Point p = new Point();
1327     p.move(3.0, 4.0);
1328     assertEquals(5.0, p.distanceFromOrigin());
1329 jsr166 1.41 p.moveIfAtOrigin(5.0, 12.0);
1330     assertEquals(5.0, p.distanceFromOrigin2());
1331     }
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 jsr166 1.39 }
1393 jsr166 1.40
1394 jsr166 1.44 /**
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 dl 1.47 final List<CompletableFuture<?>> futures = new ArrayList<>();
1405 jsr166 1.44 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 jsr166 1.1 }