ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/test/tck/StampedLockTest.java
Revision: 1.44
Committed: Sun Sep 29 20:19:43 2019 UTC (4 years, 7 months ago) by jsr166
Branch: MAIN
Changes since 1.43: +147 -38 lines
Log Message:
add testConcurrentAccess

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     long s = 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 dl 1.4 }
362    
363     /**
364 jsr166 1.27 * interruptible operations throw InterruptedException when read locked and interrupted
365 dl 1.4 */
366 jsr166 1.27 public void testInterruptibleOperationsThrowInterruptedExceptionReadLockedInterrupted() {
367 dl 1.4 final StampedLock lock = new StampedLock();
368 jsr166 1.27 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 jsr166 1.12
378 jsr166 1.27 assertThrowInterruptedExceptionWhenInterrupted(interruptibleLockBlockingActions);
379 dl 1.4 }
380    
381     /**
382 jsr166 1.27 * Non-interruptible operations ignore and preserve interrupt status
383 dl 1.4 */
384 jsr166 1.27 public void testNonInterruptibleOperationsIgnoreInterrupts() {
385 dl 1.4 final StampedLock lock = new StampedLock();
386 jsr166 1.27 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 jsr166 1.12
408 jsr166 1.27 assertTrue(Thread.interrupted());
409 dl 1.4 }
410    
411     /**
412     * tryWriteLock on an unlocked lock succeeds
413     */
414 jsr166 1.27 public void testTryWriteLock() {
415 dl 1.4 final StampedLock lock = new StampedLock();
416     long s = lock.tryWriteLock();
417     assertTrue(s != 0L);
418     assertTrue(lock.isWriteLocked());
419 jsr166 1.27 assertEquals(0L, lock.tryWriteLock());
420 dl 1.4 releaseWriteLock(lock, s);
421     }
422    
423     /**
424     * tryWriteLock fails if locked
425     */
426 jsr166 1.27 public void testTryWriteLockWhenLocked() {
427 dl 1.4 final StampedLock lock = new StampedLock();
428     long s = lock.writeLock();
429     Thread t = newStartedThread(new CheckedRunnable() {
430     public void realRun() {
431 jsr166 1.27 assertEquals(0L, lock.tryWriteLock());
432 dl 1.4 }});
433 jsr166 1.12
434 jsr166 1.27 assertEquals(0L, lock.tryWriteLock());
435 dl 1.4 awaitTermination(t);
436     releaseWriteLock(lock, s);
437     }
438    
439     /**
440     * tryReadLock fails if write-locked
441     */
442 jsr166 1.27 public void testTryReadLockWhenLocked() {
443 dl 1.4 final StampedLock lock = new StampedLock();
444     long s = lock.writeLock();
445     Thread t = newStartedThread(new CheckedRunnable() {
446     public void realRun() {
447 jsr166 1.27 assertEquals(0L, lock.tryReadLock());
448 dl 1.4 }});
449 jsr166 1.12
450 jsr166 1.27 assertEquals(0L, lock.tryReadLock());
451 dl 1.4 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 jsr166 1.27 assertValid(lock, s2);
465 dl 1.4 lock.unlockRead(s2);
466     long s3 = lock.tryReadLock(LONG_DELAY_MS, MILLISECONDS);
467 jsr166 1.27 assertValid(lock, s3);
468 dl 1.4 lock.unlockRead(s3);
469     long s4 = lock.readLock();
470 jsr166 1.27 assertValid(lock, s4);
471 dl 1.4 lock.unlockRead(s4);
472 jsr166 1.27 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 dl 1.4 }});
479 jsr166 1.12
480 dl 1.4 awaitTermination(t);
481     lock.unlockRead(s);
482     }
483    
484     /**
485 jsr166 1.33 * writeLock() succeeds only after a reading thread unlocks
486 dl 1.4 */
487 jsr166 1.11 public void testWriteAfterReadLock() throws InterruptedException {
488 jsr166 1.33 final CountDownLatch aboutToLock = new CountDownLatch(1);
489 dl 1.4 final StampedLock lock = new StampedLock();
490     long rs = lock.readLock();
491     Thread t = newStartedThread(new CheckedRunnable() {
492     public void realRun() {
493 jsr166 1.33 aboutToLock.countDown();
494 dl 1.4 long s = lock.writeLock();
495 jsr166 1.33 assertTrue(lock.isWriteLocked());
496     assertFalse(lock.isReadLocked());
497 dl 1.4 lock.unlockWrite(s);
498     }});
499 jsr166 1.12
500 jsr166 1.34 await(aboutToLock);
501 jsr166 1.35 assertThreadBlocks(t, Thread.State.WAITING);
502 jsr166 1.11 assertFalse(lock.isWriteLocked());
503 jsr166 1.33 assertTrue(lock.isReadLocked());
504 jsr166 1.11 lock.unlockRead(rs);
505     awaitTermination(t);
506 jsr166 1.33 assertUnlocked(lock);
507 dl 1.4 }
508    
509     /**
510 jsr166 1.33 * writeLock() succeeds only after reading threads unlock
511 dl 1.4 */
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 jsr166 1.12
521 dl 1.4 awaitTermination(t1);
522    
523     Thread t2 = newStartedThread(new CheckedRunnable() {
524     public void realRun() {
525     long ws = lock.writeLock();
526     lock.unlockWrite(ws);
527     }});
528 jsr166 1.12
529 jsr166 1.27 assertTrue(lock.isReadLocked());
530 dl 1.4 assertFalse(lock.isWriteLocked());
531     lock.unlockRead(s);
532     awaitTermination(t2);
533 jsr166 1.33 assertUnlocked(lock);
534 dl 1.4 }
535    
536     /**
537 jsr166 1.33 * readLock() succeed only after a writing thread unlocks
538 dl 1.4 */
539     public void testReadAfterWriteLock() {
540     final StampedLock lock = new StampedLock();
541 jsr166 1.27 final CountDownLatch threadsStarted = new CountDownLatch(2);
542 dl 1.4 final long s = lock.writeLock();
543 jsr166 1.33 final Runnable acquireReleaseReadLock = new CheckedRunnable() {
544 dl 1.4 public void realRun() {
545 jsr166 1.27 threadsStarted.countDown();
546 dl 1.4 long rs = lock.readLock();
547 jsr166 1.33 assertTrue(lock.isReadLocked());
548     assertFalse(lock.isWriteLocked());
549 dl 1.4 lock.unlockRead(rs);
550 jsr166 1.33 }};
551     Thread t1 = newStartedThread(acquireReleaseReadLock);
552     Thread t2 = newStartedThread(acquireReleaseReadLock);
553 dl 1.4
554 jsr166 1.27 await(threadsStarted);
555 jsr166 1.35 assertThreadBlocks(t1, Thread.State.WAITING);
556     assertThreadBlocks(t2, Thread.State.WAITING);
557 jsr166 1.33 assertTrue(lock.isWriteLocked());
558     assertFalse(lock.isReadLocked());
559 dl 1.4 releaseWriteLock(lock, s);
560     awaitTermination(t1);
561     awaitTermination(t2);
562 jsr166 1.33 assertUnlocked(lock);
563 dl 1.4 }
564    
565     /**
566 jsr166 1.27 * tryReadLock succeeds if read locked but not write locked
567 dl 1.4 */
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 jsr166 1.27 assertValid(lock, rs);
575 dl 1.4 lock.unlockRead(rs);
576     }});
577    
578     awaitTermination(t);
579     lock.unlockRead(s);
580     }
581    
582     /**
583 jsr166 1.27 * tryWriteLock fails when read locked
584 dl 1.4 */
585 jsr166 1.27 public void testTryWriteLockWhenReadLocked() {
586 dl 1.4 final StampedLock lock = new StampedLock();
587     long s = lock.readLock();
588     Thread t = newStartedThread(new CheckedRunnable() {
589     public void realRun() {
590 jsr166 1.42 assertEquals(0L, lock.tryWriteLock());
591 dl 1.4 }});
592    
593     awaitTermination(t);
594     lock.unlockRead(s);
595     }
596    
597     /**
598 jsr166 1.27 * timed lock operations time out if lock not available
599 dl 1.4 */
600 jsr166 1.27 public void testTimedLock_Timeout() throws Exception {
601     ArrayList<Future<?>> futures = new ArrayList<>();
602    
603     // Write locked
604 dl 1.4 final StampedLock lock = new StampedLock();
605 jsr166 1.27 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 dl 1.4 public void realRun() throws InterruptedException {
617     long startTime = System.nanoTime();
618 jsr166 1.27 assertEquals(0L, lock.tryWriteLock(timeoutMillis(), MILLISECONDS));
619     assertTrue(millisElapsedSince(startTime) >= timeoutMillis());
620     }}));
621 dl 1.4
622 jsr166 1.27 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 dl 1.4
637 jsr166 1.27 futures.add(cachedThreadPool.submit(new CheckedRunnable() {
638 dl 1.4 public void realRun() throws InterruptedException {
639     long startTime = System.nanoTime();
640 jsr166 1.27 assertEquals(0L, lock2.tryWriteLock(timeoutMillis(), MILLISECONDS));
641     assertTrue(millisElapsedSince(startTime) >= timeoutMillis());
642     }}));
643    
644     for (Future<?> future : futures)
645     assertNull(future.get());
646 jsr166 1.7
647 jsr166 1.27 releaseWriteLock(lock, stamp);
648     releaseReadLock(lock2, stamp2);
649 dl 1.4 }
650    
651     /**
652 jsr166 1.27 * writeLockInterruptibly succeeds if unlocked
653 dl 1.4 */
654 jsr166 1.11 public void testWriteLockInterruptibly() throws InterruptedException {
655 dl 1.4 final StampedLock lock = new StampedLock();
656 jsr166 1.11 long s = lock.writeLockInterruptibly();
657     assertTrue(lock.isWriteLocked());
658     releaseWriteLock(lock, s);
659 dl 1.4 }
660    
661     /**
662 jsr166 1.27 * readLockInterruptibly succeeds if lock free
663 dl 1.4 */
664 jsr166 1.11 public void testReadLockInterruptibly() throws InterruptedException {
665 dl 1.4 final StampedLock lock = new StampedLock();
666 jsr166 1.27
667     long s = assertValid(lock, lock.readLockInterruptibly());
668     assertTrue(lock.isReadLocked());
669 jsr166 1.11 lock.unlockRead(s);
670 jsr166 1.12
671 jsr166 1.27 lock.asReadLock().lockInterruptibly();
672     assertTrue(lock.isReadLocked());
673     lock.asReadLock().unlock();
674 dl 1.4 }
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 dl 1.5
691 dl 1.4 /**
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 jsr166 1.27 * tryOptimisticRead succeeds and validates if unlocked, fails if
706     * exclusively locked
707 dl 1.4 */
708 jsr166 1.11 public void testValidateOptimistic() throws InterruptedException {
709     StampedLock lock = new StampedLock();
710 jsr166 1.27
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 dl 1.4 }
728    
729     /**
730     * tryOptimisticRead stamp does not validate if a write lock intervenes
731     */
732     public void testValidateOptimisticWriteLocked() {
733 jsr166 1.27 final StampedLock lock = new StampedLock();
734     final long p = assertValid(lock, lock.tryOptimisticRead());
735     final long s = assertValid(lock, lock.writeLock());
736 dl 1.4 assertFalse(lock.validate(p));
737 jsr166 1.27 assertEquals(0L, lock.tryOptimisticRead());
738 dl 1.4 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 jsr166 1.11 public void testValidateOptimisticWriteLocked2()
747     throws InterruptedException {
748 jsr166 1.32 final CountDownLatch locked = new CountDownLatch(1);
749 dl 1.4 final StampedLock lock = new StampedLock();
750 jsr166 1.27 final long p = assertValid(lock, lock.tryOptimisticRead());
751    
752 dl 1.4 Thread t = newStartedThread(new CheckedInterruptedRunnable() {
753 jsr166 1.11 public void realRun() throws InterruptedException {
754     lock.writeLockInterruptibly();
755 jsr166 1.32 locked.countDown();
756 jsr166 1.11 lock.writeLockInterruptibly();
757     }});
758 jsr166 1.12
759 jsr166 1.34 await(locked);
760 jsr166 1.11 assertFalse(lock.validate(p));
761 jsr166 1.27 assertEquals(0L, lock.tryOptimisticRead());
762 jsr166 1.35 assertThreadBlocks(t, Thread.State.WAITING);
763 jsr166 1.11 t.interrupt();
764     awaitTermination(t);
765 jsr166 1.33 assertTrue(lock.isWriteLocked());
766 dl 1.4 }
767    
768     /**
769 jsr166 1.27 * tryConvertToOptimisticRead succeeds and validates if successfully locked
770 dl 1.4 */
771 jsr166 1.11 public void testTryConvertToOptimisticRead() throws InterruptedException {
772     StampedLock lock = new StampedLock();
773 jsr166 1.27 long s, p, q;
774 jsr166 1.19 assertEquals(0L, lock.tryConvertToOptimisticRead(0L));
775    
776 jsr166 1.27 s = assertValid(lock, lock.tryOptimisticRead());
777 jsr166 1.19 assertEquals(s, lock.tryConvertToOptimisticRead(s));
778     assertTrue(lock.validate(s));
779    
780 jsr166 1.27 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 jsr166 1.20
788 jsr166 1.27 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 dl 1.4 }
802    
803     /**
804 jsr166 1.27 * tryConvertToReadLock succeeds for valid stamps
805 dl 1.4 */
806 jsr166 1.11 public void testTryConvertToReadLock() throws InterruptedException {
807     StampedLock lock = new StampedLock();
808     long s, p;
809 jsr166 1.22
810 jsr166 1.27 assertEquals(0L, lock.tryConvertToReadLock(0L));
811 jsr166 1.22
812 jsr166 1.27 s = assertValid(lock, lock.tryOptimisticRead());
813     p = assertValid(lock, lock.tryConvertToReadLock(s));
814 jsr166 1.22 assertTrue(lock.isReadLocked());
815     assertEquals(1, lock.getReadLockCount());
816 jsr166 1.27 assertTrue(lock.validate(s));
817 jsr166 1.11 lock.unlockRead(p);
818 jsr166 1.22
819 jsr166 1.27 s = assertValid(lock, lock.tryOptimisticRead());
820 jsr166 1.24 lock.readLock();
821 jsr166 1.27 p = assertValid(lock, lock.tryConvertToReadLock(s));
822 jsr166 1.24 assertTrue(lock.isReadLocked());
823     assertEquals(2, lock.getReadLockCount());
824     lock.unlockRead(p);
825     lock.unlockRead(p);
826 jsr166 1.27 assertUnlocked(lock);
827 jsr166 1.24
828 jsr166 1.27 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 dl 1.4 }
848    
849     /**
850 jsr166 1.27 * tryConvertToWriteLock succeeds if lock available; fails if multiply read locked
851 dl 1.4 */
852 jsr166 1.11 public void testTryConvertToWriteLock() throws InterruptedException {
853     StampedLock lock = new StampedLock();
854     long s, p;
855 jsr166 1.21
856 jsr166 1.27 assertEquals(0L, lock.tryConvertToWriteLock(0L));
857 jsr166 1.21
858 jsr166 1.11 assertTrue((s = lock.tryOptimisticRead()) != 0L);
859     assertTrue((p = lock.tryConvertToWriteLock(s)) != 0L);
860 jsr166 1.23 assertTrue(lock.isWriteLocked());
861 jsr166 1.11 lock.unlockWrite(p);
862 jsr166 1.21
863 jsr166 1.27 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 jsr166 1.21
882 jsr166 1.27 // 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 dl 1.4 }
895    
896     /**
897     * asWriteLock can be locked and unlocked
898     */
899 jsr166 1.27 public void testAsWriteLock() throws Throwable {
900 dl 1.4 StampedLock sl = new StampedLock();
901     Lock lock = sl.asWriteLock();
902 jsr166 1.27 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 dl 1.4 }
911    
912     /**
913     * asReadLock can be locked and unlocked
914     */
915 jsr166 1.27 public void testAsReadLock() throws Throwable {
916 dl 1.4 StampedLock sl = new StampedLock();
917     Lock lock = sl.asReadLock();
918 jsr166 1.27 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 dl 1.4 }
931    
932     /**
933     * asReadWriteLock.writeLock can be locked and unlocked
934     */
935 jsr166 1.27 public void testAsReadWriteLockWriteLock() throws Throwable {
936 dl 1.4 StampedLock sl = new StampedLock();
937     Lock lock = sl.asReadWriteLock().writeLock();
938 jsr166 1.27 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 dl 1.4 }
947    
948     /**
949     * asReadWriteLock.readLock can be locked and unlocked
950     */
951 jsr166 1.27 public void testAsReadWriteLockReadLock() throws Throwable {
952 dl 1.4 StampedLock sl = new StampedLock();
953     Lock lock = sl.asReadWriteLock().readLock();
954 jsr166 1.27 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 dl 1.4 }
967 jsr166 1.1
968 jsr166 1.15 /**
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 jsr166 1.16 /**
981     * Passing optimistic read stamps to unlock operations result in
982     * IllegalMonitorStateException
983     */
984     public void testCannotUnlockOptimisticReadStamps() {
985 jsr166 1.43 {
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 jsr166 1.16
1020 jsr166 1.43 {
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 jsr166 1.17
1050 jsr166 1.43 {
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 jsr166 1.16 }
1097    
1098 jsr166 1.25 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 jsr166 1.26 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 jsr166 1.25 /**
1119 jsr166 1.27 * Invalid stamps result in IllegalMonitorStateException
1120 jsr166 1.25 */
1121 jsr166 1.27 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 jsr166 1.25
1145 jsr166 1.27 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 jsr166 1.26
1159 jsr166 1.27 for (Function<StampedLock, Long> writeLocker : writeLockers())
1160     for (BiConsumer<StampedLock, Long> writeUnlocker : writeUnlockers()) {
1161 jsr166 1.26 final long stamp = writeLocker.apply(sl);
1162 jsr166 1.27 assertValid(sl, stamp);
1163     assertNoLongerValidStampsThrow.run();
1164 jsr166 1.26 assertThrows(IllegalMonitorStateException.class,
1165 jsr166 1.27 () -> sl.unlockRead(stamp),
1166     () -> sl.unlockWrite(0L));
1167 jsr166 1.26 writeUnlocker.accept(sl, stamp);
1168 jsr166 1.27 assertUnlocked(sl);
1169     assertNoLongerValidStampsThrow.run();
1170 jsr166 1.26 }
1171     }
1172    
1173     /**
1174 jsr166 1.27 * Read locks can be very deeply nested
1175 jsr166 1.26 */
1176 jsr166 1.27 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 jsr166 1.25 }
1197 jsr166 1.27 assertUnlocked(lock);
1198 jsr166 1.25 }
1199 jsr166 1.38
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 jsr166 1.39
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 jsr166 1.41
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 jsr166 1.39 }
1320    
1321     Point p = new Point();
1322     p.move(3.0, 4.0);
1323     assertEquals(5.0, p.distanceFromOrigin());
1324 jsr166 1.41 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 jsr166 1.39 }
1388 jsr166 1.40
1389 jsr166 1.44 /**
1390     * Multiple threads repeatedly contend for the same lock.
1391     */
1392     public void testConcurrentAccess() throws Exception {
1393     final StampedLock sl = new StampedLock();
1394     final Lock wl = sl.asWriteLock();
1395     final Lock rl = sl.asReadLock();
1396     final long testDurationMillis = expensiveTests ? 1000 : 2;
1397     final int nTasks = ThreadLocalRandom.current().nextInt(1, 10);
1398     final AtomicBoolean done = new AtomicBoolean(false);
1399     final List<CompletableFuture> futures = new ArrayList<>();
1400     final List<Callable<Long>> stampedWriteLockers = List.of(
1401     () -> sl.writeLock(),
1402     () -> writeLockInterruptiblyUninterrupted(sl),
1403     () -> tryWriteLockUninterrupted(sl, LONG_DELAY_MS, MILLISECONDS),
1404     () -> {
1405     long stamp;
1406     do { stamp = sl.tryConvertToWriteLock(sl.tryOptimisticRead()); }
1407     while (stamp == 0L);
1408     return stamp;
1409     },
1410     () -> {
1411     long stamp;
1412     do { stamp = sl.tryWriteLock(); } while (stamp == 0L);
1413     return stamp;
1414     },
1415     () -> {
1416     long stamp;
1417     do { stamp = sl.tryWriteLock(0L, DAYS); } while (stamp == 0L);
1418     return stamp;
1419     });
1420     final List<Callable<Long>> stampedReadLockers = List.of(
1421     () -> sl.readLock(),
1422     () -> readLockInterruptiblyUninterrupted(sl),
1423     () -> tryReadLockUninterrupted(sl, LONG_DELAY_MS, MILLISECONDS),
1424     () -> {
1425     long stamp;
1426     do { stamp = sl.tryConvertToReadLock(sl.tryOptimisticRead()); }
1427     while (stamp == 0L);
1428     return stamp;
1429     },
1430     () -> {
1431     long stamp;
1432     do { stamp = sl.tryReadLock(); } while (stamp == 0L);
1433     return stamp;
1434     },
1435     () -> {
1436     long stamp;
1437     do { stamp = sl.tryReadLock(0L, DAYS); } while (stamp == 0L);
1438     return stamp;
1439     });
1440     final List<Consumer<Long>> stampedWriteUnlockers = List.of(
1441     stamp -> sl.unlockWrite(stamp),
1442     stamp -> sl.unlock(stamp),
1443     stamp -> assertTrue(sl.tryUnlockWrite()),
1444     stamp -> wl.unlock(),
1445     stamp -> sl.tryConvertToOptimisticRead(stamp));
1446     final List<Consumer<Long>> stampedReadUnlockers = List.of(
1447     stamp -> sl.unlockRead(stamp),
1448     stamp -> sl.unlock(stamp),
1449     stamp -> assertTrue(sl.tryUnlockRead()),
1450     stamp -> rl.unlock(),
1451     stamp -> sl.tryConvertToOptimisticRead(stamp));
1452     final Action writer = () -> {
1453     // repeatedly acquires write lock
1454     var locker = chooseRandomly(stampedWriteLockers);
1455     var unlocker = chooseRandomly(stampedWriteUnlockers);
1456     while (!done.getAcquire()) {
1457     long stamp = locker.call();
1458     try {
1459     assertTrue(isWriteLockStamp(stamp));
1460     assertTrue(sl.isWriteLocked());
1461     assertFalse(isReadLockStamp(stamp));
1462     assertFalse(sl.isReadLocked());
1463     assertEquals(0, sl.getReadLockCount());
1464     assertTrue(sl.validate(stamp));
1465     } finally {
1466     unlocker.accept(stamp);
1467     }
1468     }
1469     };
1470     final Action reader = () -> {
1471     // repeatedly acquires read lock
1472     var locker = chooseRandomly(stampedReadLockers);
1473     var unlocker = chooseRandomly(stampedReadUnlockers);
1474     while (!done.getAcquire()) {
1475     long stamp = locker.call();
1476     try {
1477     assertFalse(isWriteLockStamp(stamp));
1478     assertFalse(sl.isWriteLocked());
1479     assertTrue(isReadLockStamp(stamp));
1480     assertTrue(sl.isReadLocked());
1481     assertTrue(sl.getReadLockCount() > 0);
1482     assertTrue(sl.validate(stamp));
1483     } finally {
1484     unlocker.accept(stamp);
1485     }
1486     }
1487     };
1488     for (int i = nTasks; i--> 0; ) {
1489     Action task = chooseRandomly(writer, reader);
1490     futures.add(CompletableFuture.runAsync(checkedRunnable(task)));
1491     }
1492     Thread.sleep(testDurationMillis);
1493     done.setRelease(true);
1494     for (var future : futures)
1495     checkTimedGet(future, null);
1496     }
1497    
1498 jsr166 1.1 }