ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/test/tck/StampedLockTest.java
Revision: 1.43
Committed: Fri Feb 22 19:27:47 2019 UTC (5 years, 2 months ago) by jsr166
Branch: MAIN
Changes since 1.42: +109 -98 lines
Log Message:
improve assertThrows tests

File Contents

# Content
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 import static java.util.concurrent.TimeUnit.DAYS;
9 import static java.util.concurrent.TimeUnit.MILLISECONDS;
10
11 import static java.util.concurrent.locks.StampedLock.isLockStamp;
12 import static java.util.concurrent.locks.StampedLock.isOptimisticReadStamp;
13 import static java.util.concurrent.locks.StampedLock.isReadLockStamp;
14 import static java.util.concurrent.locks.StampedLock.isWriteLockStamp;
15
16 import java.util.ArrayList;
17 import java.util.List;
18 import java.util.concurrent.CountDownLatch;
19 import java.util.concurrent.Future;
20 import java.util.concurrent.TimeUnit;
21 import java.util.concurrent.locks.Lock;
22 import java.util.concurrent.locks.StampedLock;
23 import java.util.function.BiConsumer;
24 import java.util.function.Function;
25
26 import junit.framework.Test;
27 import junit.framework.TestSuite;
28
29 public class StampedLockTest extends JSR166TestCase {
30 public static void main(String[] args) {
31 main(suite(), args);
32 }
33 public static Test suite() {
34 return new TestSuite(StampedLockTest.class);
35 }
36
37 /**
38 * Releases write lock, checking isWriteLocked before and after
39 */
40 void releaseWriteLock(StampedLock lock, long stamp) {
41 assertTrue(lock.isWriteLocked());
42 assertValid(lock, stamp);
43 lock.unlockWrite(stamp);
44 assertFalse(lock.isWriteLocked());
45 assertFalse(lock.validate(stamp));
46 }
47
48 /**
49 * Releases read lock, checking isReadLocked before and after
50 */
51 void releaseReadLock(StampedLock lock, long stamp) {
52 assertTrue(lock.isReadLocked());
53 assertValid(lock, stamp);
54 lock.unlockRead(stamp);
55 assertFalse(lock.isReadLocked());
56 assertTrue(lock.validate(stamp));
57 }
58
59 long assertNonZero(long v) {
60 assertTrue(v != 0L);
61 return v;
62 }
63
64 long assertValid(StampedLock lock, long stamp) {
65 assertTrue(stamp != 0L);
66 assertTrue(lock.validate(stamp));
67 return stamp;
68 }
69
70 void assertUnlocked(StampedLock lock) {
71 assertFalse(lock.isReadLocked());
72 assertFalse(lock.isWriteLocked());
73 assertEquals(0, lock.getReadLockCount());
74 assertValid(lock, lock.tryOptimisticRead());
75 }
76
77 List<Action> lockLockers(Lock lock) {
78 List<Action> lockers = new ArrayList<>();
79 lockers.add(() -> lock.lock());
80 lockers.add(() -> lock.lockInterruptibly());
81 lockers.add(() -> lock.tryLock());
82 lockers.add(() -> lock.tryLock(Long.MIN_VALUE, DAYS));
83 lockers.add(() -> lock.tryLock(0L, DAYS));
84 lockers.add(() -> lock.tryLock(Long.MAX_VALUE, DAYS));
85 return lockers;
86 }
87
88 List<Function<StampedLock, Long>> readLockers() {
89 List<Function<StampedLock, Long>> readLockers = new ArrayList<>();
90 readLockers.add(sl -> sl.readLock());
91 readLockers.add(sl -> sl.tryReadLock());
92 readLockers.add(sl -> readLockInterruptiblyUninterrupted(sl));
93 readLockers.add(sl -> tryReadLockUninterrupted(sl, Long.MIN_VALUE, DAYS));
94 readLockers.add(sl -> tryReadLockUninterrupted(sl, 0L, DAYS));
95 readLockers.add(sl -> sl.tryConvertToReadLock(sl.tryOptimisticRead()));
96 return readLockers;
97 }
98
99 List<BiConsumer<StampedLock, Long>> readUnlockers() {
100 List<BiConsumer<StampedLock, Long>> readUnlockers = new ArrayList<>();
101 readUnlockers.add((sl, stamp) -> sl.unlockRead(stamp));
102 readUnlockers.add((sl, stamp) -> assertTrue(sl.tryUnlockRead()));
103 readUnlockers.add((sl, stamp) -> sl.asReadLock().unlock());
104 readUnlockers.add((sl, stamp) -> sl.unlock(stamp));
105 readUnlockers.add((sl, stamp) -> assertValid(sl, sl.tryConvertToOptimisticRead(stamp)));
106 return readUnlockers;
107 }
108
109 List<Function<StampedLock, Long>> writeLockers() {
110 List<Function<StampedLock, Long>> writeLockers = new ArrayList<>();
111 writeLockers.add(sl -> sl.writeLock());
112 writeLockers.add(sl -> sl.tryWriteLock());
113 writeLockers.add(sl -> writeLockInterruptiblyUninterrupted(sl));
114 writeLockers.add(sl -> tryWriteLockUninterrupted(sl, Long.MIN_VALUE, DAYS));
115 writeLockers.add(sl -> tryWriteLockUninterrupted(sl, 0L, DAYS));
116 writeLockers.add(sl -> sl.tryConvertToWriteLock(sl.tryOptimisticRead()));
117 return writeLockers;
118 }
119
120 List<BiConsumer<StampedLock, Long>> writeUnlockers() {
121 List<BiConsumer<StampedLock, Long>> writeUnlockers = new ArrayList<>();
122 writeUnlockers.add((sl, stamp) -> sl.unlockWrite(stamp));
123 writeUnlockers.add((sl, stamp) -> assertTrue(sl.tryUnlockWrite()));
124 writeUnlockers.add((sl, stamp) -> sl.asWriteLock().unlock());
125 writeUnlockers.add((sl, stamp) -> sl.unlock(stamp));
126 writeUnlockers.add((sl, stamp) -> assertValid(sl, sl.tryConvertToOptimisticRead(stamp)));
127 return writeUnlockers;
128 }
129
130 /**
131 * Constructed StampedLock is in unlocked state
132 */
133 public void testConstructor() {
134 assertUnlocked(new StampedLock());
135 }
136
137 /**
138 * write-locking, then unlocking, an unlocked lock succeed
139 */
140 public void testWriteLock_lockUnlock() {
141 StampedLock lock = new StampedLock();
142
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 }
158
159 /**
160 * read-locking, then unlocking, an unlocked lock succeed
161 */
162 public void testReadLock_lockUnlock() {
163 StampedLock lock = new StampedLock();
164
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 }
183
184 /**
185 * tryUnlockWrite fails if not write locked
186 */
187 public void testTryUnlockWrite_failure() {
188 StampedLock lock = new StampedLock();
189 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 }
200
201 /**
202 * tryUnlockRead fails if not read locked
203 */
204 public void testTryUnlockRead_failure() {
205 StampedLock lock = new StampedLock();
206 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 }
217
218 /**
219 * validate(0L) fails
220 */
221 public void testValidate0() {
222 StampedLock lock = new StampedLock();
223 assertFalse(lock.validate(0L));
224 }
225
226 /**
227 * A stamp obtained from a successful lock operation validates while the lock is held
228 */
229 public void testValidate() throws InterruptedException {
230 StampedLock lock = new StampedLock();
231
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 }
246
247 /**
248 * A stamp obtained from an unsuccessful lock operation does not validate
249 */
250 public void testValidate2() throws InterruptedException {
251 StampedLock lock = new StampedLock();
252 long s = assertNonZero(lock.writeLock());
253 assertTrue(lock.validate(s));
254 assertFalse(lock.validate(lock.tryWriteLock()));
255 assertFalse(lock.validate(lock.tryWriteLock(randomExpiredTimeout(),
256 randomTimeUnit())));
257 assertFalse(lock.validate(lock.tryReadLock()));
258 assertFalse(lock.validate(lock.tryWriteLock(randomExpiredTimeout(),
259 randomTimeUnit())));
260 assertFalse(lock.validate(lock.tryOptimisticRead()));
261 lock.unlockWrite(s);
262 }
263
264 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 /**
278 * interruptible operations throw InterruptedException when pre-interrupted
279 */
280 public void testInterruptibleOperationsThrowInterruptedExceptionWhenPreInterrupted() {
281 final StampedLock lock = new StampedLock();
282
283 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 }
340
341 /**
342 * interruptible operations throw InterruptedException when write locked and interrupted
343 */
344 public void testInterruptibleOperationsThrowInterruptedExceptionWriteLockedInterrupted() {
345 final StampedLock lock = new StampedLock();
346 long s = lock.writeLock();
347
348 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 }
362
363 /**
364 * interruptible operations throw InterruptedException when read locked and interrupted
365 */
366 public void testInterruptibleOperationsThrowInterruptedExceptionReadLockedInterrupted() {
367 final StampedLock lock = new StampedLock();
368 long s = lock.readLock();
369
370 Action[] interruptibleLockBlockingActions = {
371 () -> lock.writeLockInterruptibly(),
372 () -> lock.tryWriteLock(Long.MAX_VALUE, DAYS),
373 () -> lock.asWriteLock().lockInterruptibly(),
374 () -> lock.asWriteLock().tryLock(Long.MAX_VALUE, DAYS),
375 };
376 shuffle(interruptibleLockBlockingActions);
377
378 assertThrowInterruptedExceptionWhenInterrupted(interruptibleLockBlockingActions);
379 }
380
381 /**
382 * Non-interruptible operations ignore and preserve interrupt status
383 */
384 public void testNonInterruptibleOperationsIgnoreInterrupts() {
385 final StampedLock lock = new StampedLock();
386 Thread.currentThread().interrupt();
387
388 for (BiConsumer<StampedLock, Long> readUnlocker : readUnlockers()) {
389 long s = assertValid(lock, lock.readLock());
390 readUnlocker.accept(lock, s);
391 s = assertValid(lock, lock.tryReadLock());
392 readUnlocker.accept(lock, s);
393 }
394
395 lock.asReadLock().lock();
396 lock.asReadLock().unlock();
397
398 for (BiConsumer<StampedLock, Long> writeUnlocker : writeUnlockers()) {
399 long s = assertValid(lock, lock.writeLock());
400 writeUnlocker.accept(lock, s);
401 s = assertValid(lock, lock.tryWriteLock());
402 writeUnlocker.accept(lock, s);
403 }
404
405 lock.asWriteLock().lock();
406 lock.asWriteLock().unlock();
407
408 assertTrue(Thread.interrupted());
409 }
410
411 /**
412 * tryWriteLock on an unlocked lock succeeds
413 */
414 public void testTryWriteLock() {
415 final StampedLock lock = new StampedLock();
416 long s = lock.tryWriteLock();
417 assertTrue(s != 0L);
418 assertTrue(lock.isWriteLocked());
419 assertEquals(0L, lock.tryWriteLock());
420 releaseWriteLock(lock, s);
421 }
422
423 /**
424 * tryWriteLock fails if locked
425 */
426 public void testTryWriteLockWhenLocked() {
427 final StampedLock lock = new StampedLock();
428 long s = lock.writeLock();
429 Thread t = newStartedThread(new CheckedRunnable() {
430 public void realRun() {
431 assertEquals(0L, lock.tryWriteLock());
432 }});
433
434 assertEquals(0L, lock.tryWriteLock());
435 awaitTermination(t);
436 releaseWriteLock(lock, s);
437 }
438
439 /**
440 * tryReadLock fails if write-locked
441 */
442 public void testTryReadLockWhenLocked() {
443 final StampedLock lock = new StampedLock();
444 long s = lock.writeLock();
445 Thread t = newStartedThread(new CheckedRunnable() {
446 public void realRun() {
447 assertEquals(0L, lock.tryReadLock());
448 }});
449
450 assertEquals(0L, lock.tryReadLock());
451 awaitTermination(t);
452 releaseWriteLock(lock, s);
453 }
454
455 /**
456 * Multiple threads can hold a read lock when not write-locked
457 */
458 public void testMultipleReadLocks() {
459 final StampedLock lock = new StampedLock();
460 final long s = lock.readLock();
461 Thread t = newStartedThread(new CheckedRunnable() {
462 public void realRun() throws InterruptedException {
463 long s2 = lock.tryReadLock();
464 assertValid(lock, s2);
465 lock.unlockRead(s2);
466 long s3 = lock.tryReadLock(LONG_DELAY_MS, MILLISECONDS);
467 assertValid(lock, s3);
468 lock.unlockRead(s3);
469 long s4 = lock.readLock();
470 assertValid(lock, s4);
471 lock.unlockRead(s4);
472 lock.asReadLock().lock();
473 lock.asReadLock().unlock();
474 lock.asReadLock().lockInterruptibly();
475 lock.asReadLock().unlock();
476 lock.asReadLock().tryLock(Long.MIN_VALUE, DAYS);
477 lock.asReadLock().unlock();
478 }});
479
480 awaitTermination(t);
481 lock.unlockRead(s);
482 }
483
484 /**
485 * writeLock() succeeds only after a reading thread unlocks
486 */
487 public void testWriteAfterReadLock() throws InterruptedException {
488 final CountDownLatch aboutToLock = new CountDownLatch(1);
489 final StampedLock lock = new StampedLock();
490 long rs = lock.readLock();
491 Thread t = newStartedThread(new CheckedRunnable() {
492 public void realRun() {
493 aboutToLock.countDown();
494 long s = lock.writeLock();
495 assertTrue(lock.isWriteLocked());
496 assertFalse(lock.isReadLocked());
497 lock.unlockWrite(s);
498 }});
499
500 await(aboutToLock);
501 assertThreadBlocks(t, Thread.State.WAITING);
502 assertFalse(lock.isWriteLocked());
503 assertTrue(lock.isReadLocked());
504 lock.unlockRead(rs);
505 awaitTermination(t);
506 assertUnlocked(lock);
507 }
508
509 /**
510 * writeLock() succeeds only after reading threads unlock
511 */
512 public void testWriteAfterMultipleReadLocks() {
513 final StampedLock lock = new StampedLock();
514 long s = lock.readLock();
515 Thread t1 = newStartedThread(new CheckedRunnable() {
516 public void realRun() {
517 long rs = lock.readLock();
518 lock.unlockRead(rs);
519 }});
520
521 awaitTermination(t1);
522
523 Thread t2 = newStartedThread(new CheckedRunnable() {
524 public void realRun() {
525 long ws = lock.writeLock();
526 lock.unlockWrite(ws);
527 }});
528
529 assertTrue(lock.isReadLocked());
530 assertFalse(lock.isWriteLocked());
531 lock.unlockRead(s);
532 awaitTermination(t2);
533 assertUnlocked(lock);
534 }
535
536 /**
537 * readLock() succeed only after a writing thread unlocks
538 */
539 public void testReadAfterWriteLock() {
540 final StampedLock lock = new StampedLock();
541 final CountDownLatch threadsStarted = new CountDownLatch(2);
542 final long s = lock.writeLock();
543 final Runnable acquireReleaseReadLock = new CheckedRunnable() {
544 public void realRun() {
545 threadsStarted.countDown();
546 long rs = lock.readLock();
547 assertTrue(lock.isReadLocked());
548 assertFalse(lock.isWriteLocked());
549 lock.unlockRead(rs);
550 }};
551 Thread t1 = newStartedThread(acquireReleaseReadLock);
552 Thread t2 = newStartedThread(acquireReleaseReadLock);
553
554 await(threadsStarted);
555 assertThreadBlocks(t1, Thread.State.WAITING);
556 assertThreadBlocks(t2, Thread.State.WAITING);
557 assertTrue(lock.isWriteLocked());
558 assertFalse(lock.isReadLocked());
559 releaseWriteLock(lock, s);
560 awaitTermination(t1);
561 awaitTermination(t2);
562 assertUnlocked(lock);
563 }
564
565 /**
566 * tryReadLock succeeds if read locked but not write locked
567 */
568 public void testTryLockWhenReadLocked() {
569 final StampedLock lock = new StampedLock();
570 long s = lock.readLock();
571 Thread t = newStartedThread(new CheckedRunnable() {
572 public void realRun() {
573 long rs = lock.tryReadLock();
574 assertValid(lock, rs);
575 lock.unlockRead(rs);
576 }});
577
578 awaitTermination(t);
579 lock.unlockRead(s);
580 }
581
582 /**
583 * tryWriteLock fails when read locked
584 */
585 public void testTryWriteLockWhenReadLocked() {
586 final StampedLock lock = new StampedLock();
587 long s = lock.readLock();
588 Thread t = newStartedThread(new CheckedRunnable() {
589 public void realRun() {
590 assertEquals(0L, lock.tryWriteLock());
591 }});
592
593 awaitTermination(t);
594 lock.unlockRead(s);
595 }
596
597 /**
598 * timed lock operations time out if lock not available
599 */
600 public void testTimedLock_Timeout() throws Exception {
601 ArrayList<Future<?>> futures = new ArrayList<>();
602
603 // Write locked
604 final StampedLock lock = new StampedLock();
605 long stamp = lock.writeLock();
606 assertEquals(0L, lock.tryReadLock(0L, DAYS));
607 assertEquals(0L, lock.tryReadLock(Long.MIN_VALUE, DAYS));
608 assertFalse(lock.asReadLock().tryLock(0L, DAYS));
609 assertFalse(lock.asReadLock().tryLock(Long.MIN_VALUE, DAYS));
610 assertEquals(0L, lock.tryWriteLock(0L, DAYS));
611 assertEquals(0L, lock.tryWriteLock(Long.MIN_VALUE, DAYS));
612 assertFalse(lock.asWriteLock().tryLock(0L, DAYS));
613 assertFalse(lock.asWriteLock().tryLock(Long.MIN_VALUE, DAYS));
614
615 futures.add(cachedThreadPool.submit(new CheckedRunnable() {
616 public void realRun() throws InterruptedException {
617 long startTime = System.nanoTime();
618 assertEquals(0L, lock.tryWriteLock(timeoutMillis(), MILLISECONDS));
619 assertTrue(millisElapsedSince(startTime) >= timeoutMillis());
620 }}));
621
622 futures.add(cachedThreadPool.submit(new CheckedRunnable() {
623 public void realRun() throws InterruptedException {
624 long startTime = System.nanoTime();
625 assertEquals(0L, lock.tryReadLock(timeoutMillis(), MILLISECONDS));
626 assertTrue(millisElapsedSince(startTime) >= timeoutMillis());
627 }}));
628
629 // Read locked
630 final StampedLock lock2 = new StampedLock();
631 long stamp2 = lock2.readLock();
632 assertEquals(0L, lock2.tryWriteLock(0L, DAYS));
633 assertEquals(0L, lock2.tryWriteLock(Long.MIN_VALUE, DAYS));
634 assertFalse(lock2.asWriteLock().tryLock(0L, DAYS));
635 assertFalse(lock2.asWriteLock().tryLock(Long.MIN_VALUE, DAYS));
636
637 futures.add(cachedThreadPool.submit(new CheckedRunnable() {
638 public void realRun() throws InterruptedException {
639 long startTime = System.nanoTime();
640 assertEquals(0L, lock2.tryWriteLock(timeoutMillis(), MILLISECONDS));
641 assertTrue(millisElapsedSince(startTime) >= timeoutMillis());
642 }}));
643
644 for (Future<?> future : futures)
645 assertNull(future.get());
646
647 releaseWriteLock(lock, stamp);
648 releaseReadLock(lock2, stamp2);
649 }
650
651 /**
652 * writeLockInterruptibly succeeds if unlocked
653 */
654 public void testWriteLockInterruptibly() throws InterruptedException {
655 final StampedLock lock = new StampedLock();
656 long s = lock.writeLockInterruptibly();
657 assertTrue(lock.isWriteLocked());
658 releaseWriteLock(lock, s);
659 }
660
661 /**
662 * readLockInterruptibly succeeds if lock free
663 */
664 public void testReadLockInterruptibly() throws InterruptedException {
665 final StampedLock lock = new StampedLock();
666
667 long s = assertValid(lock, lock.readLockInterruptibly());
668 assertTrue(lock.isReadLocked());
669 lock.unlockRead(s);
670
671 lock.asReadLock().lockInterruptibly();
672 assertTrue(lock.isReadLocked());
673 lock.asReadLock().unlock();
674 }
675
676 /**
677 * A serialized lock deserializes as unlocked
678 */
679 public void testSerialization() {
680 StampedLock lock = new StampedLock();
681 lock.writeLock();
682 StampedLock clone = serialClone(lock);
683 assertTrue(lock.isWriteLocked());
684 assertFalse(clone.isWriteLocked());
685 long s = clone.writeLock();
686 assertTrue(clone.isWriteLocked());
687 clone.unlockWrite(s);
688 assertFalse(clone.isWriteLocked());
689 }
690
691 /**
692 * toString indicates current lock state
693 */
694 public void testToString() {
695 StampedLock lock = new StampedLock();
696 assertTrue(lock.toString().contains("Unlocked"));
697 long s = lock.writeLock();
698 assertTrue(lock.toString().contains("Write-locked"));
699 lock.unlockWrite(s);
700 s = lock.readLock();
701 assertTrue(lock.toString().contains("Read-locks"));
702 }
703
704 /**
705 * tryOptimisticRead succeeds and validates if unlocked, fails if
706 * exclusively locked
707 */
708 public void testValidateOptimistic() throws InterruptedException {
709 StampedLock lock = new StampedLock();
710
711 assertValid(lock, lock.tryOptimisticRead());
712
713 for (Function<StampedLock, Long> writeLocker : writeLockers()) {
714 long s = assertValid(lock, writeLocker.apply(lock));
715 assertEquals(0L, lock.tryOptimisticRead());
716 releaseWriteLock(lock, s);
717 }
718
719 for (Function<StampedLock, Long> readLocker : readLockers()) {
720 long s = assertValid(lock, readLocker.apply(lock));
721 long p = assertValid(lock, lock.tryOptimisticRead());
722 releaseReadLock(lock, s);
723 assertTrue(lock.validate(p));
724 }
725
726 assertValid(lock, lock.tryOptimisticRead());
727 }
728
729 /**
730 * tryOptimisticRead stamp does not validate if a write lock intervenes
731 */
732 public void testValidateOptimisticWriteLocked() {
733 final StampedLock lock = new StampedLock();
734 final long p = assertValid(lock, lock.tryOptimisticRead());
735 final long s = assertValid(lock, lock.writeLock());
736 assertFalse(lock.validate(p));
737 assertEquals(0L, lock.tryOptimisticRead());
738 assertTrue(lock.validate(s));
739 lock.unlockWrite(s);
740 }
741
742 /**
743 * tryOptimisticRead stamp does not validate if a write lock
744 * intervenes in another thread
745 */
746 public void testValidateOptimisticWriteLocked2()
747 throws InterruptedException {
748 final CountDownLatch locked = new CountDownLatch(1);
749 final StampedLock lock = new StampedLock();
750 final long p = assertValid(lock, lock.tryOptimisticRead());
751
752 Thread t = newStartedThread(new CheckedInterruptedRunnable() {
753 public void realRun() throws InterruptedException {
754 lock.writeLockInterruptibly();
755 locked.countDown();
756 lock.writeLockInterruptibly();
757 }});
758
759 await(locked);
760 assertFalse(lock.validate(p));
761 assertEquals(0L, lock.tryOptimisticRead());
762 assertThreadBlocks(t, Thread.State.WAITING);
763 t.interrupt();
764 awaitTermination(t);
765 assertTrue(lock.isWriteLocked());
766 }
767
768 /**
769 * tryConvertToOptimisticRead succeeds and validates if successfully locked
770 */
771 public void testTryConvertToOptimisticRead() throws InterruptedException {
772 StampedLock lock = new StampedLock();
773 long s, p, q;
774 assertEquals(0L, lock.tryConvertToOptimisticRead(0L));
775
776 s = assertValid(lock, lock.tryOptimisticRead());
777 assertEquals(s, lock.tryConvertToOptimisticRead(s));
778 assertTrue(lock.validate(s));
779
780 for (Function<StampedLock, Long> writeLocker : writeLockers()) {
781 s = assertValid(lock, writeLocker.apply(lock));
782 p = assertValid(lock, lock.tryConvertToOptimisticRead(s));
783 assertFalse(lock.validate(s));
784 assertTrue(lock.validate(p));
785 assertUnlocked(lock);
786 }
787
788 for (Function<StampedLock, Long> readLocker : readLockers()) {
789 s = assertValid(lock, readLocker.apply(lock));
790 q = assertValid(lock, lock.tryOptimisticRead());
791 assertEquals(q, lock.tryConvertToOptimisticRead(q));
792 assertTrue(lock.validate(q));
793 assertTrue(lock.isReadLocked());
794 p = assertValid(lock, lock.tryConvertToOptimisticRead(s));
795 assertTrue(lock.validate(p));
796 assertTrue(lock.validate(s));
797 assertUnlocked(lock);
798 assertEquals(q, lock.tryConvertToOptimisticRead(q));
799 assertTrue(lock.validate(q));
800 }
801 }
802
803 /**
804 * tryConvertToReadLock succeeds for valid stamps
805 */
806 public void testTryConvertToReadLock() throws InterruptedException {
807 StampedLock lock = new StampedLock();
808 long s, p;
809
810 assertEquals(0L, lock.tryConvertToReadLock(0L));
811
812 s = assertValid(lock, lock.tryOptimisticRead());
813 p = assertValid(lock, lock.tryConvertToReadLock(s));
814 assertTrue(lock.isReadLocked());
815 assertEquals(1, lock.getReadLockCount());
816 assertTrue(lock.validate(s));
817 lock.unlockRead(p);
818
819 s = assertValid(lock, lock.tryOptimisticRead());
820 lock.readLock();
821 p = assertValid(lock, lock.tryConvertToReadLock(s));
822 assertTrue(lock.isReadLocked());
823 assertEquals(2, lock.getReadLockCount());
824 lock.unlockRead(p);
825 lock.unlockRead(p);
826 assertUnlocked(lock);
827
828 for (BiConsumer<StampedLock, Long> readUnlocker : readUnlockers()) {
829 for (Function<StampedLock, Long> writeLocker : writeLockers()) {
830 s = assertValid(lock, writeLocker.apply(lock));
831 p = assertValid(lock, lock.tryConvertToReadLock(s));
832 assertFalse(lock.validate(s));
833 assertTrue(lock.isReadLocked());
834 assertEquals(1, lock.getReadLockCount());
835 readUnlocker.accept(lock, p);
836 }
837
838 for (Function<StampedLock, Long> readLocker : readLockers()) {
839 s = assertValid(lock, readLocker.apply(lock));
840 assertEquals(s, lock.tryConvertToReadLock(s));
841 assertTrue(lock.validate(s));
842 assertTrue(lock.isReadLocked());
843 assertEquals(1, lock.getReadLockCount());
844 readUnlocker.accept(lock, s);
845 }
846 }
847 }
848
849 /**
850 * tryConvertToWriteLock succeeds if lock available; fails if multiply read locked
851 */
852 public void testTryConvertToWriteLock() throws InterruptedException {
853 StampedLock lock = new StampedLock();
854 long s, p;
855
856 assertEquals(0L, lock.tryConvertToWriteLock(0L));
857
858 assertTrue((s = lock.tryOptimisticRead()) != 0L);
859 assertTrue((p = lock.tryConvertToWriteLock(s)) != 0L);
860 assertTrue(lock.isWriteLocked());
861 lock.unlockWrite(p);
862
863 for (BiConsumer<StampedLock, Long> writeUnlocker : writeUnlockers()) {
864 for (Function<StampedLock, Long> writeLocker : writeLockers()) {
865 s = assertValid(lock, writeLocker.apply(lock));
866 assertEquals(s, lock.tryConvertToWriteLock(s));
867 assertTrue(lock.validate(s));
868 assertTrue(lock.isWriteLocked());
869 writeUnlocker.accept(lock, s);
870 }
871
872 for (Function<StampedLock, Long> readLocker : readLockers()) {
873 s = assertValid(lock, readLocker.apply(lock));
874 p = assertValid(lock, lock.tryConvertToWriteLock(s));
875 assertFalse(lock.validate(s));
876 assertTrue(lock.validate(p));
877 assertTrue(lock.isWriteLocked());
878 writeUnlocker.accept(lock, p);
879 }
880 }
881
882 // failure if multiply read locked
883 for (Function<StampedLock, Long> readLocker : readLockers()) {
884 s = assertValid(lock, readLocker.apply(lock));
885 p = assertValid(lock, readLocker.apply(lock));
886 assertEquals(0L, lock.tryConvertToWriteLock(s));
887 assertTrue(lock.validate(s));
888 assertTrue(lock.validate(p));
889 assertEquals(2, lock.getReadLockCount());
890 lock.unlock(p);
891 lock.unlock(s);
892 assertUnlocked(lock);
893 }
894 }
895
896 /**
897 * asWriteLock can be locked and unlocked
898 */
899 public void testAsWriteLock() throws Throwable {
900 StampedLock sl = new StampedLock();
901 Lock lock = sl.asWriteLock();
902 for (Action locker : lockLockers(lock)) {
903 locker.run();
904 assertTrue(sl.isWriteLocked());
905 assertFalse(sl.isReadLocked());
906 assertFalse(lock.tryLock());
907 lock.unlock();
908 assertUnlocked(sl);
909 }
910 }
911
912 /**
913 * asReadLock can be locked and unlocked
914 */
915 public void testAsReadLock() throws Throwable {
916 StampedLock sl = new StampedLock();
917 Lock lock = sl.asReadLock();
918 for (Action locker : lockLockers(lock)) {
919 locker.run();
920 assertTrue(sl.isReadLocked());
921 assertFalse(sl.isWriteLocked());
922 assertEquals(1, sl.getReadLockCount());
923 locker.run();
924 assertTrue(sl.isReadLocked());
925 assertEquals(2, sl.getReadLockCount());
926 lock.unlock();
927 lock.unlock();
928 assertUnlocked(sl);
929 }
930 }
931
932 /**
933 * asReadWriteLock.writeLock can be locked and unlocked
934 */
935 public void testAsReadWriteLockWriteLock() throws Throwable {
936 StampedLock sl = new StampedLock();
937 Lock lock = sl.asReadWriteLock().writeLock();
938 for (Action locker : lockLockers(lock)) {
939 locker.run();
940 assertTrue(sl.isWriteLocked());
941 assertFalse(sl.isReadLocked());
942 assertFalse(lock.tryLock());
943 lock.unlock();
944 assertUnlocked(sl);
945 }
946 }
947
948 /**
949 * asReadWriteLock.readLock can be locked and unlocked
950 */
951 public void testAsReadWriteLockReadLock() throws Throwable {
952 StampedLock sl = new StampedLock();
953 Lock lock = sl.asReadWriteLock().readLock();
954 for (Action locker : lockLockers(lock)) {
955 locker.run();
956 assertTrue(sl.isReadLocked());
957 assertFalse(sl.isWriteLocked());
958 assertEquals(1, sl.getReadLockCount());
959 locker.run();
960 assertTrue(sl.isReadLocked());
961 assertEquals(2, sl.getReadLockCount());
962 lock.unlock();
963 lock.unlock();
964 assertUnlocked(sl);
965 }
966 }
967
968 /**
969 * Lock.newCondition throws UnsupportedOperationException
970 */
971 public void testLockViewsDoNotSupportConditions() {
972 StampedLock sl = new StampedLock();
973 assertThrows(UnsupportedOperationException.class,
974 () -> sl.asWriteLock().newCondition(),
975 () -> sl.asReadLock().newCondition(),
976 () -> sl.asReadWriteLock().writeLock().newCondition(),
977 () -> sl.asReadWriteLock().readLock().newCondition());
978 }
979
980 /**
981 * Passing optimistic read stamps to unlock operations result in
982 * IllegalMonitorStateException
983 */
984 public void testCannotUnlockOptimisticReadStamps() {
985 {
986 StampedLock sl = new StampedLock();
987 long stamp = assertValid(sl, sl.tryOptimisticRead());
988 assertThrows(IllegalMonitorStateException.class,
989 () -> sl.unlockRead(stamp));
990 }
991 {
992 StampedLock sl = new StampedLock();
993 long stamp = sl.tryOptimisticRead();
994 assertThrows(IllegalMonitorStateException.class,
995 () -> sl.unlock(stamp));
996 }
997
998 {
999 StampedLock sl = new StampedLock();
1000 long stamp = sl.tryOptimisticRead();
1001 sl.writeLock();
1002 assertThrows(IllegalMonitorStateException.class,
1003 () -> sl.unlock(stamp));
1004 }
1005 {
1006 StampedLock sl = new StampedLock();
1007 sl.readLock();
1008 long stamp = assertValid(sl, sl.tryOptimisticRead());
1009 assertThrows(IllegalMonitorStateException.class,
1010 () -> sl.unlockRead(stamp));
1011 }
1012 {
1013 StampedLock sl = new StampedLock();
1014 sl.readLock();
1015 long stamp = assertValid(sl, sl.tryOptimisticRead());
1016 assertThrows(IllegalMonitorStateException.class,
1017 () -> sl.unlock(stamp));
1018 }
1019
1020 {
1021 StampedLock sl = new StampedLock();
1022 long stamp = sl.tryConvertToOptimisticRead(sl.writeLock());
1023 assertValid(sl, stamp);
1024 sl.writeLock();
1025 assertThrows(IllegalMonitorStateException.class,
1026 () -> sl.unlockWrite(stamp));
1027 }
1028 {
1029 StampedLock sl = new StampedLock();
1030 long stamp = sl.tryConvertToOptimisticRead(sl.writeLock());
1031 sl.writeLock();
1032 assertThrows(IllegalMonitorStateException.class,
1033 () -> sl.unlock(stamp));
1034 }
1035 {
1036 StampedLock sl = new StampedLock();
1037 long stamp = sl.tryConvertToOptimisticRead(sl.writeLock());
1038 sl.readLock();
1039 assertThrows(IllegalMonitorStateException.class,
1040 () -> sl.unlockRead(stamp));
1041 }
1042 {
1043 StampedLock sl = new StampedLock();
1044 long stamp = sl.tryConvertToOptimisticRead(sl.writeLock());
1045 sl.readLock();
1046 assertThrows(IllegalMonitorStateException.class,
1047 () -> sl.unlock(stamp));
1048 }
1049
1050 {
1051 StampedLock sl = new StampedLock();
1052 long stamp = sl.tryConvertToOptimisticRead(sl.readLock());
1053 assertValid(sl, stamp);
1054 sl.writeLock();
1055 assertThrows(IllegalMonitorStateException.class,
1056 () -> sl.unlockWrite(stamp));
1057 }
1058 {
1059 StampedLock sl = new StampedLock();
1060 long stamp = sl.tryConvertToOptimisticRead(sl.readLock());
1061 sl.writeLock();
1062 assertThrows(IllegalMonitorStateException.class,
1063 () -> sl.unlock(stamp));
1064 }
1065 {
1066 StampedLock sl = new StampedLock();
1067 long stamp = sl.tryConvertToOptimisticRead(sl.readLock());
1068 sl.readLock();
1069 assertThrows(IllegalMonitorStateException.class,
1070 () -> sl.unlockRead(stamp));
1071 }
1072 {
1073 StampedLock sl = new StampedLock();
1074 sl.readLock();
1075 long stamp = sl.tryConvertToOptimisticRead(sl.readLock());
1076 assertValid(sl, stamp);
1077 sl.readLock();
1078 assertThrows(IllegalMonitorStateException.class,
1079 () -> sl.unlockRead(stamp));
1080 }
1081 {
1082 StampedLock sl = new StampedLock();
1083 long stamp = sl.tryConvertToOptimisticRead(sl.readLock());
1084 sl.readLock();
1085 assertThrows(IllegalMonitorStateException.class,
1086 () -> sl.unlock(stamp));
1087 }
1088 {
1089 StampedLock sl = new StampedLock();
1090 sl.readLock();
1091 long stamp = sl.tryConvertToOptimisticRead(sl.readLock());
1092 sl.readLock();
1093 assertThrows(IllegalMonitorStateException.class,
1094 () -> sl.unlock(stamp));
1095 }
1096 }
1097
1098 static long writeLockInterruptiblyUninterrupted(StampedLock sl) {
1099 try { return sl.writeLockInterruptibly(); }
1100 catch (InterruptedException ex) { throw new AssertionError(ex); }
1101 }
1102
1103 static long tryWriteLockUninterrupted(StampedLock sl, long time, TimeUnit unit) {
1104 try { return sl.tryWriteLock(time, unit); }
1105 catch (InterruptedException ex) { throw new AssertionError(ex); }
1106 }
1107
1108 static long readLockInterruptiblyUninterrupted(StampedLock sl) {
1109 try { return sl.readLockInterruptibly(); }
1110 catch (InterruptedException ex) { throw new AssertionError(ex); }
1111 }
1112
1113 static long tryReadLockUninterrupted(StampedLock sl, long time, TimeUnit unit) {
1114 try { return sl.tryReadLock(time, unit); }
1115 catch (InterruptedException ex) { throw new AssertionError(ex); }
1116 }
1117
1118 /**
1119 * Invalid stamps result in IllegalMonitorStateException
1120 */
1121 public void testInvalidStampsThrowIllegalMonitorStateException() {
1122 final StampedLock sl = new StampedLock();
1123
1124 assertThrows(IllegalMonitorStateException.class,
1125 () -> sl.unlockWrite(0L),
1126 () -> sl.unlockRead(0L),
1127 () -> sl.unlock(0L));
1128
1129 final long optimisticStamp = sl.tryOptimisticRead();
1130 final long readStamp = sl.readLock();
1131 sl.unlockRead(readStamp);
1132 final long writeStamp = sl.writeLock();
1133 sl.unlockWrite(writeStamp);
1134 assertTrue(optimisticStamp != 0L && readStamp != 0L && writeStamp != 0L);
1135 final long[] noLongerValidStamps = { optimisticStamp, readStamp, writeStamp };
1136 final Runnable assertNoLongerValidStampsThrow = () -> {
1137 for (long noLongerValidStamp : noLongerValidStamps)
1138 assertThrows(IllegalMonitorStateException.class,
1139 () -> sl.unlockWrite(noLongerValidStamp),
1140 () -> sl.unlockRead(noLongerValidStamp),
1141 () -> sl.unlock(noLongerValidStamp));
1142 };
1143 assertNoLongerValidStampsThrow.run();
1144
1145 for (Function<StampedLock, Long> readLocker : readLockers())
1146 for (BiConsumer<StampedLock, Long> readUnlocker : readUnlockers()) {
1147 final long stamp = readLocker.apply(sl);
1148 assertValid(sl, stamp);
1149 assertNoLongerValidStampsThrow.run();
1150 assertThrows(IllegalMonitorStateException.class,
1151 () -> sl.unlockWrite(stamp),
1152 () -> sl.unlockRead(sl.tryOptimisticRead()),
1153 () -> sl.unlockRead(0L));
1154 readUnlocker.accept(sl, stamp);
1155 assertUnlocked(sl);
1156 assertNoLongerValidStampsThrow.run();
1157 }
1158
1159 for (Function<StampedLock, Long> writeLocker : writeLockers())
1160 for (BiConsumer<StampedLock, Long> writeUnlocker : writeUnlockers()) {
1161 final long stamp = writeLocker.apply(sl);
1162 assertValid(sl, stamp);
1163 assertNoLongerValidStampsThrow.run();
1164 assertThrows(IllegalMonitorStateException.class,
1165 () -> sl.unlockRead(stamp),
1166 () -> sl.unlockWrite(0L));
1167 writeUnlocker.accept(sl, stamp);
1168 assertUnlocked(sl);
1169 assertNoLongerValidStampsThrow.run();
1170 }
1171 }
1172
1173 /**
1174 * Read locks can be very deeply nested
1175 */
1176 public void testDeeplyNestedReadLocks() {
1177 final StampedLock lock = new StampedLock();
1178 final int depth = 300;
1179 final long[] stamps = new long[depth];
1180 final List<Function<StampedLock, Long>> readLockers = readLockers();
1181 final List<BiConsumer<StampedLock, Long>> readUnlockers = readUnlockers();
1182 for (int i = 0; i < depth; i++) {
1183 Function<StampedLock, Long> readLocker
1184 = readLockers.get(i % readLockers.size());
1185 long stamp = readLocker.apply(lock);
1186 assertEquals(i + 1, lock.getReadLockCount());
1187 assertTrue(lock.isReadLocked());
1188 stamps[i] = stamp;
1189 }
1190 for (int i = 0; i < depth; i++) {
1191 BiConsumer<StampedLock, Long> readUnlocker
1192 = readUnlockers.get(i % readUnlockers.size());
1193 assertEquals(depth - i, lock.getReadLockCount());
1194 assertTrue(lock.isReadLocked());
1195 readUnlocker.accept(lock, stamps[depth - 1 - i]);
1196 }
1197 assertUnlocked(lock);
1198 }
1199
1200 /**
1201 * Stamped locks are not reentrant.
1202 */
1203 public void testNonReentrant() throws InterruptedException {
1204 final StampedLock lock = new StampedLock();
1205 long stamp;
1206
1207 stamp = lock.writeLock();
1208 assertValid(lock, stamp);
1209 assertEquals(0L, lock.tryWriteLock(0L, DAYS));
1210 assertEquals(0L, lock.tryReadLock(0L, DAYS));
1211 assertValid(lock, stamp);
1212 lock.unlockWrite(stamp);
1213
1214 stamp = lock.tryWriteLock(1L, DAYS);
1215 assertEquals(0L, lock.tryWriteLock(0L, DAYS));
1216 assertValid(lock, stamp);
1217 lock.unlockWrite(stamp);
1218
1219 stamp = lock.readLock();
1220 assertEquals(0L, lock.tryWriteLock(0L, DAYS));
1221 assertValid(lock, stamp);
1222 lock.unlockRead(stamp);
1223 }
1224
1225 /**
1226 * """StampedLocks have no notion of ownership. Locks acquired in
1227 * one thread can be released or converted in another."""
1228 */
1229 public void testNoOwnership() throws Throwable {
1230 ArrayList<Future<?>> futures = new ArrayList<>();
1231 for (Function<StampedLock, Long> writeLocker : writeLockers())
1232 for (BiConsumer<StampedLock, Long> writeUnlocker : writeUnlockers()) {
1233 StampedLock lock = new StampedLock();
1234 long stamp = writeLocker.apply(lock);
1235 futures.add(cachedThreadPool.submit(new CheckedRunnable() {
1236 public void realRun() {
1237 writeUnlocker.accept(lock, stamp);
1238 assertUnlocked(lock);
1239 assertFalse(lock.validate(stamp));
1240 }}));
1241 }
1242 for (Future<?> future : futures)
1243 assertNull(future.get());
1244 }
1245
1246 /** Tries out sample usage code from StampedLock javadoc. */
1247 public void testSampleUsage() throws Throwable {
1248 class Point {
1249 private double x, y;
1250 private final StampedLock sl = new StampedLock();
1251
1252 void move(double deltaX, double deltaY) { // an exclusively locked method
1253 long stamp = sl.writeLock();
1254 try {
1255 x += deltaX;
1256 y += deltaY;
1257 } finally {
1258 sl.unlockWrite(stamp);
1259 }
1260 }
1261
1262 double distanceFromOrigin() { // A read-only method
1263 double currentX, currentY;
1264 long stamp = sl.tryOptimisticRead();
1265 do {
1266 if (stamp == 0L)
1267 stamp = sl.readLock();
1268 try {
1269 // possibly racy reads
1270 currentX = x;
1271 currentY = y;
1272 } finally {
1273 stamp = sl.tryConvertToOptimisticRead(stamp);
1274 }
1275 } while (stamp == 0);
1276 return Math.hypot(currentX, currentY);
1277 }
1278
1279 double distanceFromOrigin2() {
1280 long stamp = sl.tryOptimisticRead();
1281 try {
1282 retryHoldingLock:
1283 for (;; stamp = sl.readLock()) {
1284 if (stamp == 0L)
1285 continue retryHoldingLock;
1286 // possibly racy reads
1287 double currentX = x;
1288 double currentY = y;
1289 if (!sl.validate(stamp))
1290 continue retryHoldingLock;
1291 return Math.hypot(currentX, currentY);
1292 }
1293 } finally {
1294 if (StampedLock.isReadLockStamp(stamp))
1295 sl.unlockRead(stamp);
1296 }
1297 }
1298
1299 void moveIfAtOrigin(double newX, double newY) {
1300 long stamp = sl.readLock();
1301 try {
1302 while (x == 0.0 && y == 0.0) {
1303 long ws = sl.tryConvertToWriteLock(stamp);
1304 if (ws != 0L) {
1305 stamp = ws;
1306 x = newX;
1307 y = newY;
1308 return;
1309 }
1310 else {
1311 sl.unlockRead(stamp);
1312 stamp = sl.writeLock();
1313 }
1314 }
1315 } finally {
1316 sl.unlock(stamp);
1317 }
1318 }
1319 }
1320
1321 Point p = new Point();
1322 p.move(3.0, 4.0);
1323 assertEquals(5.0, p.distanceFromOrigin());
1324 p.moveIfAtOrigin(5.0, 12.0);
1325 assertEquals(5.0, p.distanceFromOrigin2());
1326 }
1327
1328 /**
1329 * Stamp inspection methods work as expected, and do not inspect
1330 * the state of the lock itself.
1331 */
1332 public void testStampStateInspectionMethods() {
1333 StampedLock lock = new StampedLock();
1334
1335 assertFalse(isWriteLockStamp(0L));
1336 assertFalse(isReadLockStamp(0L));
1337 assertFalse(isLockStamp(0L));
1338 assertFalse(isOptimisticReadStamp(0L));
1339
1340 {
1341 long stamp = lock.writeLock();
1342 for (int i = 0; i < 2; i++) {
1343 assertTrue(isWriteLockStamp(stamp));
1344 assertFalse(isReadLockStamp(stamp));
1345 assertTrue(isLockStamp(stamp));
1346 assertFalse(isOptimisticReadStamp(stamp));
1347 if (i == 0)
1348 lock.unlockWrite(stamp);
1349 }
1350 }
1351
1352 {
1353 long stamp = lock.readLock();
1354 for (int i = 0; i < 2; i++) {
1355 assertFalse(isWriteLockStamp(stamp));
1356 assertTrue(isReadLockStamp(stamp));
1357 assertTrue(isLockStamp(stamp));
1358 assertFalse(isOptimisticReadStamp(stamp));
1359 if (i == 0)
1360 lock.unlockRead(stamp);
1361 }
1362 }
1363
1364 {
1365 long optimisticStamp = lock.tryOptimisticRead();
1366 long readStamp = lock.tryConvertToReadLock(optimisticStamp);
1367 long writeStamp = lock.tryConvertToWriteLock(readStamp);
1368 for (int i = 0; i < 2; i++) {
1369 assertFalse(isWriteLockStamp(optimisticStamp));
1370 assertFalse(isReadLockStamp(optimisticStamp));
1371 assertFalse(isLockStamp(optimisticStamp));
1372 assertTrue(isOptimisticReadStamp(optimisticStamp));
1373
1374 assertFalse(isWriteLockStamp(readStamp));
1375 assertTrue(isReadLockStamp(readStamp));
1376 assertTrue(isLockStamp(readStamp));
1377 assertFalse(isOptimisticReadStamp(readStamp));
1378
1379 assertTrue(isWriteLockStamp(writeStamp));
1380 assertFalse(isReadLockStamp(writeStamp));
1381 assertTrue(isLockStamp(writeStamp));
1382 assertFalse(isOptimisticReadStamp(writeStamp));
1383 if (i == 0)
1384 lock.unlockWrite(writeStamp);
1385 }
1386 }
1387 }
1388
1389 }