ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/test/tck/StampedLockTest.java
Revision: 1.42
Committed: Mon Nov 27 23:38:11 2017 UTC (6 years, 5 months ago) by jsr166
Branch: MAIN
Changes since 1.41: +1 -1 lines
Log Message:
prefer assertEquals to threadAssertEquals

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.10 import java.util.concurrent.CountDownLatch;
19 jsr166 1.27 import java.util.concurrent.Future;
20 jsr166 1.25 import java.util.concurrent.TimeUnit;
21 jsr166 1.1 import java.util.concurrent.locks.Lock;
22 jsr166 1.2 import java.util.concurrent.locks.StampedLock;
23 jsr166 1.25 import java.util.function.BiConsumer;
24     import java.util.function.Function;
25 jsr166 1.10
26     import junit.framework.Test;
27     import junit.framework.TestSuite;
28 jsr166 1.1
29     public class StampedLockTest extends JSR166TestCase {
30     public static void main(String[] args) {
31 jsr166 1.13 main(suite(), args);
32 jsr166 1.1 }
33     public static Test suite() {
34     return new TestSuite(StampedLockTest.class);
35     }
36    
37 dl 1.4 /**
38 jsr166 1.27 * Releases write lock, checking isWriteLocked before and after
39 dl 1.4 */
40 jsr166 1.27 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 dl 1.4 }
47    
48     /**
49 jsr166 1.27 * Releases read lock, checking isReadLocked before and after
50 dl 1.4 */
51 jsr166 1.27 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 dl 1.4 }
58    
59 jsr166 1.27 long assertNonZero(long v) {
60     assertTrue(v != 0L);
61     return v;
62 dl 1.4 }
63    
64 jsr166 1.27 long assertValid(StampedLock lock, long stamp) {
65     assertTrue(stamp != 0L);
66     assertTrue(lock.validate(stamp));
67     return stamp;
68 dl 1.4 }
69    
70 jsr166 1.27 void assertUnlocked(StampedLock lock) {
71 dl 1.4 assertFalse(lock.isReadLocked());
72     assertFalse(lock.isWriteLocked());
73 jsr166 1.27 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 jsr166 1.29 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 jsr166 1.27 return readLockers;
97 dl 1.4 }
98    
99 jsr166 1.27 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 dl 1.4 }
108    
109 jsr166 1.27 List<Function<StampedLock, Long>> writeLockers() {
110     List<Function<StampedLock, Long>> writeLockers = new ArrayList<>();
111 jsr166 1.29 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 jsr166 1.27 return writeLockers;
118 dl 1.4 }
119    
120 jsr166 1.27 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 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     Runnable[] actions = {
986     () -> {
987     StampedLock sl = new StampedLock();
988 jsr166 1.27 long stamp = assertValid(sl, sl.tryOptimisticRead());
989 jsr166 1.16 sl.unlockRead(stamp);
990     },
991     () -> {
992     StampedLock sl = new StampedLock();
993     long stamp = sl.tryOptimisticRead();
994     sl.unlock(stamp);
995     },
996    
997     () -> {
998     StampedLock sl = new StampedLock();
999     long stamp = sl.tryOptimisticRead();
1000     sl.writeLock();
1001     sl.unlock(stamp);
1002     },
1003     () -> {
1004     StampedLock sl = new StampedLock();
1005     sl.readLock();
1006 jsr166 1.27 long stamp = assertValid(sl, sl.tryOptimisticRead());
1007 jsr166 1.16 sl.unlockRead(stamp);
1008     },
1009     () -> {
1010     StampedLock sl = new StampedLock();
1011     sl.readLock();
1012 jsr166 1.27 long stamp = assertValid(sl, sl.tryOptimisticRead());
1013 jsr166 1.16 sl.unlock(stamp);
1014     },
1015    
1016     () -> {
1017     StampedLock sl = new StampedLock();
1018     long stamp = sl.tryConvertToOptimisticRead(sl.writeLock());
1019 jsr166 1.27 assertValid(sl, stamp);
1020 jsr166 1.16 sl.writeLock();
1021     sl.unlockWrite(stamp);
1022     },
1023     () -> {
1024     StampedLock sl = new StampedLock();
1025     long stamp = sl.tryConvertToOptimisticRead(sl.writeLock());
1026     sl.writeLock();
1027     sl.unlock(stamp);
1028     },
1029     () -> {
1030     StampedLock sl = new StampedLock();
1031     long stamp = sl.tryConvertToOptimisticRead(sl.writeLock());
1032     sl.readLock();
1033     sl.unlockRead(stamp);
1034     },
1035     () -> {
1036     StampedLock sl = new StampedLock();
1037     long stamp = sl.tryConvertToOptimisticRead(sl.writeLock());
1038     sl.readLock();
1039     sl.unlock(stamp);
1040     },
1041    
1042     () -> {
1043     StampedLock sl = new StampedLock();
1044     long stamp = sl.tryConvertToOptimisticRead(sl.readLock());
1045 jsr166 1.27 assertValid(sl, stamp);
1046 jsr166 1.16 sl.writeLock();
1047     sl.unlockWrite(stamp);
1048     },
1049     () -> {
1050     StampedLock sl = new StampedLock();
1051     long stamp = sl.tryConvertToOptimisticRead(sl.readLock());
1052     sl.writeLock();
1053     sl.unlock(stamp);
1054     },
1055     () -> {
1056     StampedLock sl = new StampedLock();
1057     long stamp = sl.tryConvertToOptimisticRead(sl.readLock());
1058     sl.readLock();
1059     sl.unlockRead(stamp);
1060     },
1061     () -> {
1062     StampedLock sl = new StampedLock();
1063 jsr166 1.18 sl.readLock();
1064     long stamp = sl.tryConvertToOptimisticRead(sl.readLock());
1065 jsr166 1.27 assertValid(sl, stamp);
1066 jsr166 1.18 sl.readLock();
1067     sl.unlockRead(stamp);
1068     },
1069     () -> {
1070     StampedLock sl = new StampedLock();
1071     long stamp = sl.tryConvertToOptimisticRead(sl.readLock());
1072     sl.readLock();
1073     sl.unlock(stamp);
1074     },
1075     () -> {
1076     StampedLock sl = new StampedLock();
1077     sl.readLock();
1078 jsr166 1.16 long stamp = sl.tryConvertToOptimisticRead(sl.readLock());
1079     sl.readLock();
1080     sl.unlock(stamp);
1081     },
1082     };
1083 jsr166 1.17
1084 jsr166 1.16 assertThrows(IllegalMonitorStateException.class, actions);
1085     }
1086    
1087 jsr166 1.25 static long writeLockInterruptiblyUninterrupted(StampedLock sl) {
1088     try { return sl.writeLockInterruptibly(); }
1089     catch (InterruptedException ex) { throw new AssertionError(ex); }
1090     }
1091    
1092     static long tryWriteLockUninterrupted(StampedLock sl, long time, TimeUnit unit) {
1093     try { return sl.tryWriteLock(time, unit); }
1094     catch (InterruptedException ex) { throw new AssertionError(ex); }
1095     }
1096    
1097 jsr166 1.26 static long readLockInterruptiblyUninterrupted(StampedLock sl) {
1098     try { return sl.readLockInterruptibly(); }
1099     catch (InterruptedException ex) { throw new AssertionError(ex); }
1100     }
1101    
1102     static long tryReadLockUninterrupted(StampedLock sl, long time, TimeUnit unit) {
1103     try { return sl.tryReadLock(time, unit); }
1104     catch (InterruptedException ex) { throw new AssertionError(ex); }
1105     }
1106    
1107 jsr166 1.25 /**
1108 jsr166 1.27 * Invalid stamps result in IllegalMonitorStateException
1109 jsr166 1.25 */
1110 jsr166 1.27 public void testInvalidStampsThrowIllegalMonitorStateException() {
1111     final StampedLock sl = new StampedLock();
1112    
1113     assertThrows(IllegalMonitorStateException.class,
1114     () -> sl.unlockWrite(0L),
1115     () -> sl.unlockRead(0L),
1116     () -> sl.unlock(0L));
1117    
1118     final long optimisticStamp = sl.tryOptimisticRead();
1119     final long readStamp = sl.readLock();
1120     sl.unlockRead(readStamp);
1121     final long writeStamp = sl.writeLock();
1122     sl.unlockWrite(writeStamp);
1123     assertTrue(optimisticStamp != 0L && readStamp != 0L && writeStamp != 0L);
1124     final long[] noLongerValidStamps = { optimisticStamp, readStamp, writeStamp };
1125     final Runnable assertNoLongerValidStampsThrow = () -> {
1126     for (long noLongerValidStamp : noLongerValidStamps)
1127     assertThrows(IllegalMonitorStateException.class,
1128     () -> sl.unlockWrite(noLongerValidStamp),
1129     () -> sl.unlockRead(noLongerValidStamp),
1130     () -> sl.unlock(noLongerValidStamp));
1131     };
1132     assertNoLongerValidStampsThrow.run();
1133 jsr166 1.25
1134 jsr166 1.27 for (Function<StampedLock, Long> readLocker : readLockers())
1135     for (BiConsumer<StampedLock, Long> readUnlocker : readUnlockers()) {
1136     final long stamp = readLocker.apply(sl);
1137     assertValid(sl, stamp);
1138     assertNoLongerValidStampsThrow.run();
1139     assertThrows(IllegalMonitorStateException.class,
1140     () -> sl.unlockWrite(stamp),
1141     () -> sl.unlockRead(sl.tryOptimisticRead()),
1142     () -> sl.unlockRead(0L));
1143     readUnlocker.accept(sl, stamp);
1144     assertUnlocked(sl);
1145     assertNoLongerValidStampsThrow.run();
1146     }
1147 jsr166 1.26
1148 jsr166 1.27 for (Function<StampedLock, Long> writeLocker : writeLockers())
1149     for (BiConsumer<StampedLock, Long> writeUnlocker : writeUnlockers()) {
1150 jsr166 1.26 final long stamp = writeLocker.apply(sl);
1151 jsr166 1.27 assertValid(sl, stamp);
1152     assertNoLongerValidStampsThrow.run();
1153 jsr166 1.26 assertThrows(IllegalMonitorStateException.class,
1154 jsr166 1.27 () -> sl.unlockRead(stamp),
1155     () -> sl.unlockWrite(0L));
1156 jsr166 1.26 writeUnlocker.accept(sl, stamp);
1157 jsr166 1.27 assertUnlocked(sl);
1158     assertNoLongerValidStampsThrow.run();
1159 jsr166 1.26 }
1160     }
1161    
1162     /**
1163 jsr166 1.27 * Read locks can be very deeply nested
1164 jsr166 1.26 */
1165 jsr166 1.27 public void testDeeplyNestedReadLocks() {
1166     final StampedLock lock = new StampedLock();
1167     final int depth = 300;
1168     final long[] stamps = new long[depth];
1169     final List<Function<StampedLock, Long>> readLockers = readLockers();
1170     final List<BiConsumer<StampedLock, Long>> readUnlockers = readUnlockers();
1171     for (int i = 0; i < depth; i++) {
1172     Function<StampedLock, Long> readLocker
1173     = readLockers.get(i % readLockers.size());
1174     long stamp = readLocker.apply(lock);
1175     assertEquals(i + 1, lock.getReadLockCount());
1176     assertTrue(lock.isReadLocked());
1177     stamps[i] = stamp;
1178     }
1179     for (int i = 0; i < depth; i++) {
1180     BiConsumer<StampedLock, Long> readUnlocker
1181     = readUnlockers.get(i % readUnlockers.size());
1182     assertEquals(depth - i, lock.getReadLockCount());
1183     assertTrue(lock.isReadLocked());
1184     readUnlocker.accept(lock, stamps[depth - 1 - i]);
1185 jsr166 1.25 }
1186 jsr166 1.27 assertUnlocked(lock);
1187 jsr166 1.25 }
1188 jsr166 1.38
1189     /**
1190     * Stamped locks are not reentrant.
1191     */
1192     public void testNonReentrant() throws InterruptedException {
1193     final StampedLock lock = new StampedLock();
1194     long stamp;
1195    
1196     stamp = lock.writeLock();
1197     assertValid(lock, stamp);
1198     assertEquals(0L, lock.tryWriteLock(0L, DAYS));
1199     assertEquals(0L, lock.tryReadLock(0L, DAYS));
1200     assertValid(lock, stamp);
1201     lock.unlockWrite(stamp);
1202    
1203     stamp = lock.tryWriteLock(1L, DAYS);
1204     assertEquals(0L, lock.tryWriteLock(0L, DAYS));
1205     assertValid(lock, stamp);
1206     lock.unlockWrite(stamp);
1207    
1208     stamp = lock.readLock();
1209     assertEquals(0L, lock.tryWriteLock(0L, DAYS));
1210     assertValid(lock, stamp);
1211     lock.unlockRead(stamp);
1212     }
1213    
1214     /**
1215     * """StampedLocks have no notion of ownership. Locks acquired in
1216     * one thread can be released or converted in another."""
1217     */
1218     public void testNoOwnership() throws Throwable {
1219     ArrayList<Future<?>> futures = new ArrayList<>();
1220     for (Function<StampedLock, Long> writeLocker : writeLockers())
1221     for (BiConsumer<StampedLock, Long> writeUnlocker : writeUnlockers()) {
1222     StampedLock lock = new StampedLock();
1223     long stamp = writeLocker.apply(lock);
1224     futures.add(cachedThreadPool.submit(new CheckedRunnable() {
1225     public void realRun() {
1226     writeUnlocker.accept(lock, stamp);
1227     assertUnlocked(lock);
1228     assertFalse(lock.validate(stamp));
1229     }}));
1230     }
1231     for (Future<?> future : futures)
1232     assertNull(future.get());
1233     }
1234 jsr166 1.39
1235     /** Tries out sample usage code from StampedLock javadoc. */
1236     public void testSampleUsage() throws Throwable {
1237     class Point {
1238     private double x, y;
1239     private final StampedLock sl = new StampedLock();
1240    
1241     void move(double deltaX, double deltaY) { // an exclusively locked method
1242     long stamp = sl.writeLock();
1243     try {
1244     x += deltaX;
1245     y += deltaY;
1246     } finally {
1247     sl.unlockWrite(stamp);
1248     }
1249     }
1250    
1251     double distanceFromOrigin() { // A read-only method
1252     double currentX, currentY;
1253     long stamp = sl.tryOptimisticRead();
1254     do {
1255     if (stamp == 0L)
1256     stamp = sl.readLock();
1257     try {
1258     // possibly racy reads
1259     currentX = x;
1260     currentY = y;
1261     } finally {
1262     stamp = sl.tryConvertToOptimisticRead(stamp);
1263     }
1264     } while (stamp == 0);
1265     return Math.hypot(currentX, currentY);
1266     }
1267 jsr166 1.41
1268     double distanceFromOrigin2() {
1269     long stamp = sl.tryOptimisticRead();
1270     try {
1271     retryHoldingLock:
1272     for (;; stamp = sl.readLock()) {
1273     if (stamp == 0L)
1274     continue retryHoldingLock;
1275     // possibly racy reads
1276     double currentX = x;
1277     double currentY = y;
1278     if (!sl.validate(stamp))
1279     continue retryHoldingLock;
1280     return Math.hypot(currentX, currentY);
1281     }
1282     } finally {
1283     if (StampedLock.isReadLockStamp(stamp))
1284     sl.unlockRead(stamp);
1285     }
1286     }
1287    
1288     void moveIfAtOrigin(double newX, double newY) {
1289     long stamp = sl.readLock();
1290     try {
1291     while (x == 0.0 && y == 0.0) {
1292     long ws = sl.tryConvertToWriteLock(stamp);
1293     if (ws != 0L) {
1294     stamp = ws;
1295     x = newX;
1296     y = newY;
1297     return;
1298     }
1299     else {
1300     sl.unlockRead(stamp);
1301     stamp = sl.writeLock();
1302     }
1303     }
1304     } finally {
1305     sl.unlock(stamp);
1306     }
1307     }
1308 jsr166 1.39 }
1309    
1310     Point p = new Point();
1311     p.move(3.0, 4.0);
1312     assertEquals(5.0, p.distanceFromOrigin());
1313 jsr166 1.41 p.moveIfAtOrigin(5.0, 12.0);
1314     assertEquals(5.0, p.distanceFromOrigin2());
1315     }
1316    
1317     /**
1318     * Stamp inspection methods work as expected, and do not inspect
1319     * the state of the lock itself.
1320     */
1321     public void testStampStateInspectionMethods() {
1322     StampedLock lock = new StampedLock();
1323    
1324     assertFalse(isWriteLockStamp(0L));
1325     assertFalse(isReadLockStamp(0L));
1326     assertFalse(isLockStamp(0L));
1327     assertFalse(isOptimisticReadStamp(0L));
1328    
1329     {
1330     long stamp = lock.writeLock();
1331     for (int i = 0; i < 2; i++) {
1332     assertTrue(isWriteLockStamp(stamp));
1333     assertFalse(isReadLockStamp(stamp));
1334     assertTrue(isLockStamp(stamp));
1335     assertFalse(isOptimisticReadStamp(stamp));
1336     if (i == 0)
1337     lock.unlockWrite(stamp);
1338     }
1339     }
1340    
1341     {
1342     long stamp = lock.readLock();
1343     for (int i = 0; i < 2; i++) {
1344     assertFalse(isWriteLockStamp(stamp));
1345     assertTrue(isReadLockStamp(stamp));
1346     assertTrue(isLockStamp(stamp));
1347     assertFalse(isOptimisticReadStamp(stamp));
1348     if (i == 0)
1349     lock.unlockRead(stamp);
1350     }
1351     }
1352    
1353     {
1354     long optimisticStamp = lock.tryOptimisticRead();
1355     long readStamp = lock.tryConvertToReadLock(optimisticStamp);
1356     long writeStamp = lock.tryConvertToWriteLock(readStamp);
1357     for (int i = 0; i < 2; i++) {
1358     assertFalse(isWriteLockStamp(optimisticStamp));
1359     assertFalse(isReadLockStamp(optimisticStamp));
1360     assertFalse(isLockStamp(optimisticStamp));
1361     assertTrue(isOptimisticReadStamp(optimisticStamp));
1362    
1363     assertFalse(isWriteLockStamp(readStamp));
1364     assertTrue(isReadLockStamp(readStamp));
1365     assertTrue(isLockStamp(readStamp));
1366     assertFalse(isOptimisticReadStamp(readStamp));
1367    
1368     assertTrue(isWriteLockStamp(writeStamp));
1369     assertFalse(isReadLockStamp(writeStamp));
1370     assertTrue(isLockStamp(writeStamp));
1371     assertFalse(isOptimisticReadStamp(writeStamp));
1372     if (i == 0)
1373     lock.unlockWrite(writeStamp);
1374     }
1375     }
1376 jsr166 1.39 }
1377 jsr166 1.40
1378 jsr166 1.1 }