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
8package jsr166;
9
10import static java.util.concurrent.TimeUnit.MILLISECONDS;
11
12import java.util.concurrent.CountDownLatch;
13import java.util.concurrent.locks.Lock;
14import java.util.concurrent.locks.StampedLock;
15
16import junit.framework.Test;
17import junit.framework.TestSuite;
18
19public class StampedLockTest extends JSR166TestCase {
20    // android-note: Removed because the CTS runner does a bad job of
21    // retrying tests that have suite() declarations.
22    //
23    // public static void main(String[] args) {
24    //     main(suite(), args);
25    // }
26    // public static Test suite() {
27    //     return new TestSuite(StampedLockTest.class);
28    // }
29
30    /**
31     * A runnable calling writeLockInterruptibly
32     */
33    class InterruptibleLockRunnable extends CheckedRunnable {
34        final StampedLock lock;
35        InterruptibleLockRunnable(StampedLock l) { lock = l; }
36        public void realRun() throws InterruptedException {
37            lock.writeLockInterruptibly();
38        }
39    }
40
41    /**
42     * A runnable calling writeLockInterruptibly that expects to be
43     * interrupted
44     */
45    class InterruptedLockRunnable extends CheckedInterruptedRunnable {
46        final StampedLock lock;
47        InterruptedLockRunnable(StampedLock l) { lock = l; }
48        public void realRun() throws InterruptedException {
49            lock.writeLockInterruptibly();
50        }
51    }
52
53    /**
54     * Releases write lock, checking isWriteLocked before and after
55     */
56    void releaseWriteLock(StampedLock lock, long s) {
57        assertTrue(lock.isWriteLocked());
58        lock.unlockWrite(s);
59        assertFalse(lock.isWriteLocked());
60    }
61
62    /**
63     * Constructed StampedLock is in unlocked state
64     */
65    public void testConstructor() {
66        StampedLock lock;
67        lock = new StampedLock();
68        assertFalse(lock.isWriteLocked());
69        assertFalse(lock.isReadLocked());
70        assertEquals(lock.getReadLockCount(), 0);
71    }
72
73    /**
74     * write-locking and read-locking an unlocked lock succeed
75     */
76    public void testLock() {
77        StampedLock lock = new StampedLock();
78        assertFalse(lock.isWriteLocked());
79        assertFalse(lock.isReadLocked());
80        assertEquals(lock.getReadLockCount(), 0);
81        long s = lock.writeLock();
82        assertTrue(lock.isWriteLocked());
83        assertFalse(lock.isReadLocked());
84        assertEquals(lock.getReadLockCount(), 0);
85        lock.unlockWrite(s);
86        assertFalse(lock.isWriteLocked());
87        assertFalse(lock.isReadLocked());
88        assertEquals(lock.getReadLockCount(), 0);
89        long rs = lock.readLock();
90        assertFalse(lock.isWriteLocked());
91        assertTrue(lock.isReadLocked());
92        assertEquals(lock.getReadLockCount(), 1);
93        lock.unlockRead(rs);
94        assertFalse(lock.isWriteLocked());
95        assertFalse(lock.isReadLocked());
96        assertEquals(lock.getReadLockCount(), 0);
97    }
98
99    /**
100     * unlock releases either a read or write lock
101     */
102    public void testUnlock() {
103        StampedLock lock = new StampedLock();
104        assertFalse(lock.isWriteLocked());
105        assertFalse(lock.isReadLocked());
106        assertEquals(lock.getReadLockCount(), 0);
107        long s = lock.writeLock();
108        assertTrue(lock.isWriteLocked());
109        assertFalse(lock.isReadLocked());
110        assertEquals(lock.getReadLockCount(), 0);
111        lock.unlock(s);
112        assertFalse(lock.isWriteLocked());
113        assertFalse(lock.isReadLocked());
114        assertEquals(lock.getReadLockCount(), 0);
115        long rs = lock.readLock();
116        assertFalse(lock.isWriteLocked());
117        assertTrue(lock.isReadLocked());
118        assertEquals(lock.getReadLockCount(), 1);
119        lock.unlock(rs);
120        assertFalse(lock.isWriteLocked());
121        assertFalse(lock.isReadLocked());
122        assertEquals(lock.getReadLockCount(), 0);
123    }
124
125    /**
126     * tryUnlockRead/Write succeeds if locked in associated mode else
127     * returns false
128     */
129    public void testTryUnlock() {
130        StampedLock lock = new StampedLock();
131        assertFalse(lock.isWriteLocked());
132        assertFalse(lock.isReadLocked());
133        assertEquals(lock.getReadLockCount(), 0);
134        long s = lock.writeLock();
135        assertTrue(lock.isWriteLocked());
136        assertFalse(lock.isReadLocked());
137        assertEquals(lock.getReadLockCount(), 0);
138        assertFalse(lock.tryUnlockRead());
139        assertTrue(lock.tryUnlockWrite());
140        assertFalse(lock.tryUnlockWrite());
141        assertFalse(lock.tryUnlockRead());
142        assertFalse(lock.isWriteLocked());
143        assertFalse(lock.isReadLocked());
144        assertEquals(lock.getReadLockCount(), 0);
145        long rs = lock.readLock();
146        assertFalse(lock.isWriteLocked());
147        assertTrue(lock.isReadLocked());
148        assertEquals(lock.getReadLockCount(), 1);
149        assertFalse(lock.tryUnlockWrite());
150        assertTrue(lock.tryUnlockRead());
151        assertFalse(lock.tryUnlockRead());
152        assertFalse(lock.tryUnlockWrite());
153        assertFalse(lock.isWriteLocked());
154        assertFalse(lock.isReadLocked());
155        assertEquals(lock.getReadLockCount(), 0);
156    }
157
158    /**
159     * write-unlocking an unlocked lock throws IllegalMonitorStateException
160     */
161    public void testWriteUnlock_IMSE() {
162        StampedLock lock = new StampedLock();
163        try {
164            lock.unlockWrite(0L);
165            shouldThrow();
166        } catch (IllegalMonitorStateException success) {}
167    }
168
169    /**
170     * write-unlocking an unlocked lock throws IllegalMonitorStateException
171     */
172    public void testWriteUnlock_IMSE2() {
173        StampedLock lock = new StampedLock();
174        long s = lock.writeLock();
175        lock.unlockWrite(s);
176        try {
177            lock.unlockWrite(s);
178            shouldThrow();
179        } catch (IllegalMonitorStateException success) {}
180    }
181
182    /**
183     * write-unlocking after readlock throws IllegalMonitorStateException
184     */
185    public void testWriteUnlock_IMSE3() {
186        StampedLock lock = new StampedLock();
187        long s = lock.readLock();
188        try {
189            lock.unlockWrite(s);
190            shouldThrow();
191        } catch (IllegalMonitorStateException success) {}
192    }
193
194    /**
195     * read-unlocking an unlocked lock throws IllegalMonitorStateException
196     */
197    public void testReadUnlock_IMSE() {
198        StampedLock lock = new StampedLock();
199        long s = lock.readLock();
200        lock.unlockRead(s);
201        try {
202            lock.unlockRead(s);
203            shouldThrow();
204        } catch (IllegalMonitorStateException success) {}
205    }
206
207    /**
208     * read-unlocking an unlocked lock throws IllegalMonitorStateException
209     */
210    public void testReadUnlock_IMSE2() {
211        StampedLock lock = new StampedLock();
212        try {
213            lock.unlockRead(0L);
214            shouldThrow();
215        } catch (IllegalMonitorStateException success) {}
216    }
217
218    /**
219     * read-unlocking after writeLock throws IllegalMonitorStateException
220     */
221    public void testReadUnlock_IMSE3() {
222        StampedLock lock = new StampedLock();
223        long s = lock.writeLock();
224        try {
225            lock.unlockRead(s);
226            shouldThrow();
227        } catch (IllegalMonitorStateException success) {}
228    }
229
230    /**
231     * validate(0) fails
232     */
233    public void testValidate0() {
234        StampedLock lock = new StampedLock();
235        assertFalse(lock.validate(0L));
236    }
237
238    /**
239     * A stamp obtained from a successful lock operation validates
240     */
241    public void testValidate() throws InterruptedException {
242        StampedLock lock = new StampedLock();
243        long s = lock.writeLock();
244        assertTrue(lock.validate(s));
245        lock.unlockWrite(s);
246        s = lock.readLock();
247        assertTrue(lock.validate(s));
248        lock.unlockRead(s);
249        assertTrue((s = lock.tryWriteLock()) != 0L);
250        assertTrue(lock.validate(s));
251        lock.unlockWrite(s);
252        assertTrue((s = lock.tryReadLock()) != 0L);
253        assertTrue(lock.validate(s));
254        lock.unlockRead(s);
255        assertTrue((s = lock.tryWriteLock(100L, MILLISECONDS)) != 0L);
256        assertTrue(lock.validate(s));
257        lock.unlockWrite(s);
258        assertTrue((s = lock.tryReadLock(100L, MILLISECONDS)) != 0L);
259        assertTrue(lock.validate(s));
260        lock.unlockRead(s);
261        assertTrue((s = lock.tryOptimisticRead()) != 0L);
262    }
263
264    /**
265     * A stamp obtained from an unsuccessful lock operation does not validate
266     */
267    public void testValidate2() throws InterruptedException {
268        StampedLock lock = new StampedLock();
269        long s;
270        assertTrue((s = lock.writeLock()) != 0L);
271        assertTrue(lock.validate(s));
272        assertFalse(lock.validate(lock.tryWriteLock()));
273        assertFalse(lock.validate(lock.tryWriteLock(10L, MILLISECONDS)));
274        assertFalse(lock.validate(lock.tryReadLock()));
275        assertFalse(lock.validate(lock.tryReadLock(10L, MILLISECONDS)));
276        assertFalse(lock.validate(lock.tryOptimisticRead()));
277        lock.unlockWrite(s);
278    }
279
280    /**
281     * writeLockInterruptibly is interruptible
282     */
283    public void testWriteLockInterruptibly_Interruptible()
284            throws InterruptedException {
285        final CountDownLatch running = new CountDownLatch(1);
286        final StampedLock lock = new StampedLock();
287        long s = lock.writeLock();
288        Thread t = newStartedThread(new CheckedInterruptedRunnable() {
289            public void realRun() throws InterruptedException {
290                running.countDown();
291                lock.writeLockInterruptibly();
292            }});
293
294        running.await();
295        waitForThreadToEnterWaitState(t, 100);
296        t.interrupt();
297        awaitTermination(t);
298        releaseWriteLock(lock, s);
299    }
300
301    /**
302     * timed tryWriteLock is interruptible
303     */
304    public void testWriteTryLock_Interruptible() throws InterruptedException {
305        final CountDownLatch running = new CountDownLatch(1);
306        final StampedLock lock = new StampedLock();
307        long s = lock.writeLock();
308        Thread t = newStartedThread(new CheckedInterruptedRunnable() {
309            public void realRun() throws InterruptedException {
310                running.countDown();
311                lock.tryWriteLock(2 * LONG_DELAY_MS, MILLISECONDS);
312            }});
313
314        running.await();
315        waitForThreadToEnterWaitState(t, 100);
316        t.interrupt();
317        awaitTermination(t);
318        releaseWriteLock(lock, s);
319    }
320
321    /**
322     * readLockInterruptibly is interruptible
323     */
324    public void testReadLockInterruptibly_Interruptible()
325            throws InterruptedException {
326        final CountDownLatch running = new CountDownLatch(1);
327        final StampedLock lock = new StampedLock();
328        long s = lock.writeLock();
329        Thread t = newStartedThread(new CheckedInterruptedRunnable() {
330            public void realRun() throws InterruptedException {
331                running.countDown();
332                lock.readLockInterruptibly();
333            }});
334
335        running.await();
336        waitForThreadToEnterWaitState(t, 100);
337        t.interrupt();
338        awaitTermination(t);
339        releaseWriteLock(lock, s);
340    }
341
342    /**
343     * timed tryReadLock is interruptible
344     */
345    public void testReadTryLock_Interruptible() throws InterruptedException {
346        final CountDownLatch running = new CountDownLatch(1);
347        final StampedLock lock = new StampedLock();
348        long s = lock.writeLock();
349        Thread t = newStartedThread(new CheckedInterruptedRunnable() {
350            public void realRun() throws InterruptedException {
351                running.countDown();
352                lock.tryReadLock(2 * LONG_DELAY_MS, MILLISECONDS);
353            }});
354
355        running.await();
356        waitForThreadToEnterWaitState(t, 100);
357        t.interrupt();
358        awaitTermination(t);
359        releaseWriteLock(lock, s);
360    }
361
362    /**
363     * tryWriteLock on an unlocked lock succeeds
364     */
365    public void testWriteTryLock() {
366        final StampedLock lock = new StampedLock();
367        long s = lock.tryWriteLock();
368        assertTrue(s != 0L);
369        assertTrue(lock.isWriteLocked());
370        long s2 = lock.tryWriteLock();
371        assertEquals(s2, 0L);
372        releaseWriteLock(lock, s);
373    }
374
375    /**
376     * tryWriteLock fails if locked
377     */
378    public void testWriteTryLockWhenLocked() {
379        final StampedLock lock = new StampedLock();
380        long s = lock.writeLock();
381        Thread t = newStartedThread(new CheckedRunnable() {
382            public void realRun() {
383                long ws = lock.tryWriteLock();
384                assertTrue(ws == 0L);
385            }});
386
387        awaitTermination(t);
388        releaseWriteLock(lock, s);
389    }
390
391    /**
392     * tryReadLock fails if write-locked
393     */
394    public void testReadTryLockWhenLocked() {
395        final StampedLock lock = new StampedLock();
396        long s = lock.writeLock();
397        Thread t = newStartedThread(new CheckedRunnable() {
398            public void realRun() {
399                long rs = lock.tryReadLock();
400                assertEquals(rs, 0L);
401            }});
402
403        awaitTermination(t);
404        releaseWriteLock(lock, s);
405    }
406
407    /**
408     * Multiple threads can hold a read lock when not write-locked
409     */
410    public void testMultipleReadLocks() {
411        final StampedLock lock = new StampedLock();
412        final long s = lock.readLock();
413        Thread t = newStartedThread(new CheckedRunnable() {
414            public void realRun() throws InterruptedException {
415                long s2 = lock.tryReadLock();
416                assertTrue(s2 != 0L);
417                lock.unlockRead(s2);
418                long s3 = lock.tryReadLock(LONG_DELAY_MS, MILLISECONDS);
419                assertTrue(s3 != 0L);
420                lock.unlockRead(s3);
421                long s4 = lock.readLock();
422                lock.unlockRead(s4);
423            }});
424
425        awaitTermination(t);
426        lock.unlockRead(s);
427    }
428
429    /**
430     * A writelock succeeds only after a reading thread unlocks
431     */
432    public void testWriteAfterReadLock() throws InterruptedException {
433        final CountDownLatch running = new CountDownLatch(1);
434        final StampedLock lock = new StampedLock();
435        long rs = lock.readLock();
436        Thread t = newStartedThread(new CheckedRunnable() {
437            public void realRun() {
438                running.countDown();
439                long s = lock.writeLock();
440                lock.unlockWrite(s);
441            }});
442
443        running.await();
444        waitForThreadToEnterWaitState(t, 100);
445        assertFalse(lock.isWriteLocked());
446        lock.unlockRead(rs);
447        awaitTermination(t);
448        assertFalse(lock.isWriteLocked());
449    }
450
451    /**
452     * A writelock succeeds only after reading threads unlock
453     */
454    public void testWriteAfterMultipleReadLocks() {
455        final StampedLock lock = new StampedLock();
456        long s = lock.readLock();
457        Thread t1 = newStartedThread(new CheckedRunnable() {
458            public void realRun() {
459                long rs = lock.readLock();
460                lock.unlockRead(rs);
461            }});
462
463        awaitTermination(t1);
464
465        Thread t2 = newStartedThread(new CheckedRunnable() {
466            public void realRun() {
467                long ws = lock.writeLock();
468                lock.unlockWrite(ws);
469            }});
470
471        assertFalse(lock.isWriteLocked());
472        lock.unlockRead(s);
473        awaitTermination(t2);
474        assertFalse(lock.isWriteLocked());
475    }
476
477    /**
478     * Readlocks succeed only after a writing thread unlocks
479     */
480    public void testReadAfterWriteLock() {
481        final StampedLock lock = new StampedLock();
482        final long s = lock.writeLock();
483        Thread t1 = newStartedThread(new CheckedRunnable() {
484            public void realRun() {
485                long rs = lock.readLock();
486                lock.unlockRead(rs);
487            }});
488        Thread t2 = newStartedThread(new CheckedRunnable() {
489            public void realRun() {
490                long rs = lock.readLock();
491                lock.unlockRead(rs);
492            }});
493
494        releaseWriteLock(lock, s);
495        awaitTermination(t1);
496        awaitTermination(t2);
497    }
498
499    /**
500     * tryReadLock succeeds if readlocked but not writelocked
501     */
502    public void testTryLockWhenReadLocked() {
503        final StampedLock lock = new StampedLock();
504        long s = lock.readLock();
505        Thread t = newStartedThread(new CheckedRunnable() {
506            public void realRun() {
507                long rs = lock.tryReadLock();
508                threadAssertTrue(rs != 0L);
509                lock.unlockRead(rs);
510            }});
511
512        awaitTermination(t);
513        lock.unlockRead(s);
514    }
515
516    /**
517     * tryWriteLock fails when readlocked
518     */
519    public void testWriteTryLockWhenReadLocked() {
520        final StampedLock lock = new StampedLock();
521        long s = lock.readLock();
522        Thread t = newStartedThread(new CheckedRunnable() {
523            public void realRun() {
524                long ws = lock.tryWriteLock();
525                threadAssertEquals(ws, 0L);
526            }});
527
528        awaitTermination(t);
529        lock.unlockRead(s);
530    }
531
532    /**
533     * timed tryWriteLock times out if locked
534     */
535    public void testWriteTryLock_Timeout() {
536        final StampedLock lock = new StampedLock();
537        long s = lock.writeLock();
538        Thread t = newStartedThread(new CheckedRunnable() {
539            public void realRun() throws InterruptedException {
540                long startTime = System.nanoTime();
541                long timeoutMillis = 10;
542                long ws = lock.tryWriteLock(timeoutMillis, MILLISECONDS);
543                assertEquals(ws, 0L);
544                assertTrue(millisElapsedSince(startTime) >= timeoutMillis);
545            }});
546
547        awaitTermination(t);
548        releaseWriteLock(lock, s);
549    }
550
551    /**
552     * timed tryReadLock times out if write-locked
553     */
554    public void testReadTryLock_Timeout() {
555        final StampedLock lock = new StampedLock();
556        long s = lock.writeLock();
557        Thread t = newStartedThread(new CheckedRunnable() {
558            public void realRun() throws InterruptedException {
559                long startTime = System.nanoTime();
560                long timeoutMillis = 10;
561                long rs = lock.tryReadLock(timeoutMillis, MILLISECONDS);
562                assertEquals(rs, 0L);
563                assertTrue(millisElapsedSince(startTime) >= timeoutMillis);
564            }});
565
566        awaitTermination(t);
567        assertTrue(lock.isWriteLocked());
568        lock.unlockWrite(s);
569    }
570
571    /**
572     * writeLockInterruptibly succeeds if unlocked, else is interruptible
573     */
574    public void testWriteLockInterruptibly() throws InterruptedException {
575        final CountDownLatch running = new CountDownLatch(1);
576        final StampedLock lock = new StampedLock();
577        long s = lock.writeLockInterruptibly();
578        Thread t = newStartedThread(new CheckedInterruptedRunnable() {
579            public void realRun() throws InterruptedException {
580                running.countDown();
581                lock.writeLockInterruptibly();
582            }});
583
584        running.await();
585        waitForThreadToEnterWaitState(t, 100);
586        t.interrupt();
587        assertTrue(lock.isWriteLocked());
588        awaitTermination(t);
589        releaseWriteLock(lock, s);
590    }
591
592    /**
593     * readLockInterruptibly succeeds if lock free else is interruptible
594     */
595    public void testReadLockInterruptibly() throws InterruptedException {
596        final CountDownLatch running = new CountDownLatch(1);
597        final StampedLock lock = new StampedLock();
598        long s;
599        s = lock.readLockInterruptibly();
600        lock.unlockRead(s);
601        s = lock.writeLockInterruptibly();
602        Thread t = newStartedThread(new CheckedInterruptedRunnable() {
603            public void realRun() throws InterruptedException {
604                running.countDown();
605                lock.readLockInterruptibly();
606            }});
607
608        running.await();
609        waitForThreadToEnterWaitState(t, 100);
610        t.interrupt();
611        awaitTermination(t);
612        releaseWriteLock(lock, s);
613    }
614
615    /**
616     * A serialized lock deserializes as unlocked
617     */
618    public void testSerialization() {
619        StampedLock lock = new StampedLock();
620        lock.writeLock();
621        StampedLock clone = serialClone(lock);
622        assertTrue(lock.isWriteLocked());
623        assertFalse(clone.isWriteLocked());
624        long s = clone.writeLock();
625        assertTrue(clone.isWriteLocked());
626        clone.unlockWrite(s);
627        assertFalse(clone.isWriteLocked());
628    }
629
630    /**
631     * toString indicates current lock state
632     */
633    public void testToString() {
634        StampedLock lock = new StampedLock();
635        assertTrue(lock.toString().contains("Unlocked"));
636        long s = lock.writeLock();
637        assertTrue(lock.toString().contains("Write-locked"));
638        lock.unlockWrite(s);
639        s = lock.readLock();
640        assertTrue(lock.toString().contains("Read-locks"));
641    }
642
643    /**
644     * tryOptimisticRead succeeds and validates if unlocked, fails if locked
645     */
646    public void testValidateOptimistic() throws InterruptedException {
647        StampedLock lock = new StampedLock();
648        long s, p;
649        assertTrue((p = lock.tryOptimisticRead()) != 0L);
650        assertTrue(lock.validate(p));
651        assertTrue((s = lock.writeLock()) != 0L);
652        assertFalse((p = lock.tryOptimisticRead()) != 0L);
653        assertTrue(lock.validate(s));
654        lock.unlockWrite(s);
655        assertTrue((p = lock.tryOptimisticRead()) != 0L);
656        assertTrue(lock.validate(p));
657        assertTrue((s = lock.readLock()) != 0L);
658        assertTrue(lock.validate(s));
659        assertTrue((p = lock.tryOptimisticRead()) != 0L);
660        assertTrue(lock.validate(p));
661        lock.unlockRead(s);
662        assertTrue((s = lock.tryWriteLock()) != 0L);
663        assertTrue(lock.validate(s));
664        assertFalse((p = lock.tryOptimisticRead()) != 0L);
665        lock.unlockWrite(s);
666        assertTrue((s = lock.tryReadLock()) != 0L);
667        assertTrue(lock.validate(s));
668        assertTrue((p = lock.tryOptimisticRead()) != 0L);
669        lock.unlockRead(s);
670        assertTrue(lock.validate(p));
671        assertTrue((s = lock.tryWriteLock(100L, MILLISECONDS)) != 0L);
672        assertFalse((p = lock.tryOptimisticRead()) != 0L);
673        assertTrue(lock.validate(s));
674        lock.unlockWrite(s);
675        assertTrue((s = lock.tryReadLock(100L, MILLISECONDS)) != 0L);
676        assertTrue(lock.validate(s));
677        assertTrue((p = lock.tryOptimisticRead()) != 0L);
678        lock.unlockRead(s);
679        assertTrue((p = lock.tryOptimisticRead()) != 0L);
680    }
681
682    /**
683     * tryOptimisticRead stamp does not validate if a write lock intervenes
684     */
685    public void testValidateOptimisticWriteLocked() {
686        StampedLock lock = new StampedLock();
687        long s, p;
688        assertTrue((p = lock.tryOptimisticRead()) != 0L);
689        assertTrue((s = lock.writeLock()) != 0L);
690        assertFalse(lock.validate(p));
691        assertFalse((p = lock.tryOptimisticRead()) != 0L);
692        assertTrue(lock.validate(s));
693        lock.unlockWrite(s);
694    }
695
696    /**
697     * tryOptimisticRead stamp does not validate if a write lock
698     * intervenes in another thread
699     */
700    public void testValidateOptimisticWriteLocked2()
701            throws InterruptedException {
702        final CountDownLatch running = new CountDownLatch(1);
703        final StampedLock lock = new StampedLock();
704        long s, p;
705        assertTrue((p = lock.tryOptimisticRead()) != 0L);
706        Thread t = newStartedThread(new CheckedInterruptedRunnable() {
707            public void realRun() throws InterruptedException {
708                lock.writeLockInterruptibly();
709                running.countDown();
710                lock.writeLockInterruptibly();
711            }});
712
713        running.await();
714        assertFalse(lock.validate(p));
715        assertFalse((p = lock.tryOptimisticRead()) != 0L);
716        t.interrupt();
717        awaitTermination(t);
718    }
719
720    /**
721     * tryConvertToOptimisticRead succeeds and validates if successfully locked,
722     */
723    public void testTryConvertToOptimisticRead() throws InterruptedException {
724        StampedLock lock = new StampedLock();
725        long s, p;
726        s = 0L;
727        assertFalse((p = lock.tryConvertToOptimisticRead(s)) != 0L);
728        assertTrue((s = lock.tryOptimisticRead()) != 0L);
729        assertTrue((p = lock.tryConvertToOptimisticRead(s)) != 0L);
730        assertTrue((s = lock.writeLock()) != 0L);
731        assertTrue((p = lock.tryConvertToOptimisticRead(s)) != 0L);
732        assertTrue(lock.validate(p));
733        assertTrue((s = lock.readLock()) != 0L);
734        assertTrue(lock.validate(s));
735        assertTrue((p = lock.tryConvertToOptimisticRead(s)) != 0L);
736        assertTrue(lock.validate(p));
737        assertTrue((s = lock.tryWriteLock()) != 0L);
738        assertTrue(lock.validate(s));
739        assertTrue((p = lock.tryConvertToOptimisticRead(s)) != 0L);
740        assertTrue(lock.validate(p));
741        assertTrue((s = lock.tryReadLock()) != 0L);
742        assertTrue(lock.validate(s));
743        assertTrue((p = lock.tryConvertToOptimisticRead(s)) != 0L);
744        assertTrue(lock.validate(p));
745        assertTrue((s = lock.tryWriteLock(100L, MILLISECONDS)) != 0L);
746        assertTrue((p = lock.tryConvertToOptimisticRead(s)) != 0L);
747        assertTrue(lock.validate(p));
748        assertTrue((s = lock.tryReadLock(100L, MILLISECONDS)) != 0L);
749        assertTrue(lock.validate(s));
750        assertTrue((p = lock.tryConvertToOptimisticRead(s)) != 0L);
751        assertTrue(lock.validate(p));
752    }
753
754    /**
755     * tryConvertToReadLock succeeds and validates if successfully locked
756     * or lock free;
757     */
758    public void testTryConvertToReadLock() throws InterruptedException {
759        StampedLock lock = new StampedLock();
760        long s, p;
761        s = 0L;
762        assertFalse((p = lock.tryConvertToReadLock(s)) != 0L);
763        assertTrue((s = lock.tryOptimisticRead()) != 0L);
764        assertTrue((p = lock.tryConvertToReadLock(s)) != 0L);
765        lock.unlockRead(p);
766        assertTrue((s = lock.writeLock()) != 0L);
767        assertTrue((p = lock.tryConvertToReadLock(s)) != 0L);
768        assertTrue(lock.validate(p));
769        lock.unlockRead(p);
770        assertTrue((s = lock.readLock()) != 0L);
771        assertTrue(lock.validate(s));
772        assertTrue((p = lock.tryConvertToReadLock(s)) != 0L);
773        assertTrue(lock.validate(p));
774        lock.unlockRead(p);
775        assertTrue((s = lock.tryWriteLock()) != 0L);
776        assertTrue(lock.validate(s));
777        assertTrue((p = lock.tryConvertToReadLock(s)) != 0L);
778        assertTrue(lock.validate(p));
779        lock.unlockRead(p);
780        assertTrue((s = lock.tryReadLock()) != 0L);
781        assertTrue(lock.validate(s));
782        assertTrue((p = lock.tryConvertToReadLock(s)) != 0L);
783        assertTrue(lock.validate(p));
784        lock.unlockRead(p);
785        assertTrue((s = lock.tryWriteLock(100L, MILLISECONDS)) != 0L);
786        assertTrue((p = lock.tryConvertToReadLock(s)) != 0L);
787        assertTrue(lock.validate(p));
788        lock.unlockRead(p);
789        assertTrue((s = lock.tryReadLock(100L, MILLISECONDS)) != 0L);
790        assertTrue(lock.validate(s));
791        assertTrue((p = lock.tryConvertToReadLock(s)) != 0L);
792        assertTrue(lock.validate(p));
793        lock.unlockRead(p);
794    }
795
796    /**
797     * tryConvertToWriteLock succeeds and validates if successfully locked
798     * or lock free;
799     */
800    public void testTryConvertToWriteLock() throws InterruptedException {
801        StampedLock lock = new StampedLock();
802        long s, p;
803        s = 0L;
804        assertFalse((p = lock.tryConvertToWriteLock(s)) != 0L);
805        assertTrue((s = lock.tryOptimisticRead()) != 0L);
806        assertTrue((p = lock.tryConvertToWriteLock(s)) != 0L);
807        lock.unlockWrite(p);
808        assertTrue((s = lock.writeLock()) != 0L);
809        assertTrue((p = lock.tryConvertToWriteLock(s)) != 0L);
810        assertTrue(lock.validate(p));
811        lock.unlockWrite(p);
812        assertTrue((s = lock.readLock()) != 0L);
813        assertTrue(lock.validate(s));
814        assertTrue((p = lock.tryConvertToWriteLock(s)) != 0L);
815        assertTrue(lock.validate(p));
816        lock.unlockWrite(p);
817        assertTrue((s = lock.tryWriteLock()) != 0L);
818        assertTrue(lock.validate(s));
819        assertTrue((p = lock.tryConvertToWriteLock(s)) != 0L);
820        assertTrue(lock.validate(p));
821        lock.unlockWrite(p);
822        assertTrue((s = lock.tryReadLock()) != 0L);
823        assertTrue(lock.validate(s));
824        assertTrue((p = lock.tryConvertToWriteLock(s)) != 0L);
825        assertTrue(lock.validate(p));
826        lock.unlockWrite(p);
827        assertTrue((s = lock.tryWriteLock(100L, MILLISECONDS)) != 0L);
828        assertTrue((p = lock.tryConvertToWriteLock(s)) != 0L);
829        assertTrue(lock.validate(p));
830        lock.unlockWrite(p);
831        assertTrue((s = lock.tryReadLock(100L, MILLISECONDS)) != 0L);
832        assertTrue(lock.validate(s));
833        assertTrue((p = lock.tryConvertToWriteLock(s)) != 0L);
834        assertTrue(lock.validate(p));
835        lock.unlockWrite(p);
836    }
837
838    /**
839     * asWriteLock can be locked and unlocked
840     */
841    public void testAsWriteLock() {
842        StampedLock sl = new StampedLock();
843        Lock lock = sl.asWriteLock();
844        lock.lock();
845        assertFalse(lock.tryLock());
846        lock.unlock();
847        assertTrue(lock.tryLock());
848    }
849
850    /**
851     * asReadLock can be locked and unlocked
852     */
853    public void testAsReadLock() {
854        StampedLock sl = new StampedLock();
855        Lock lock = sl.asReadLock();
856        lock.lock();
857        lock.unlock();
858        assertTrue(lock.tryLock());
859    }
860
861    /**
862     * asReadWriteLock.writeLock can be locked and unlocked
863     */
864    public void testAsReadWriteLockWriteLock() {
865        StampedLock sl = new StampedLock();
866        Lock lock = sl.asReadWriteLock().writeLock();
867        lock.lock();
868        assertFalse(lock.tryLock());
869        lock.unlock();
870        assertTrue(lock.tryLock());
871    }
872
873    /**
874     * asReadWriteLock.readLock can be locked and unlocked
875     */
876    public void testAsReadWriteLockReadLock() {
877        StampedLock sl = new StampedLock();
878        Lock lock = sl.asReadWriteLock().readLock();
879        lock.lock();
880        lock.unlock();
881        assertTrue(lock.tryLock());
882    }
883
884}
885