ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/test/tck/ReentrantReadWriteLockTest.java
(Generate patch)

Comparing jsr166/src/test/tck/ReentrantReadWriteLockTest.java (file contents):
Revision 1.2 by dl, Sun Sep 7 20:39:11 2003 UTC vs.
Revision 1.58 by jsr166, Sat May 7 14:43:13 2011 UTC

# Line 1 | Line 1
1   /*
2 < * Written by members of JCP JSR-166 Expert Group and released to the
3 < * public domain. Use, modify, and redistribute this code in any way
4 < * without acknowledgement. Other contributors include Andrew Wright,
5 < * Jeffrey Hayes, Pat Fischer, Mike Judd.
2 > * Written by Doug Lea with assistance from members of JCP JSR-166
3 > * Expert Group and released to the public domain, as explained at
4 > * http://creativecommons.org/publicdomain/zero/1.0/
5 > * Other contributors include Andrew Wright, Jeffrey Hayes,
6 > * Pat Fisher, Mike Judd.
7   */
8  
9   import junit.framework.*;
10 + import java.util.concurrent.atomic.AtomicBoolean;
11   import java.util.concurrent.locks.*;
12   import java.util.concurrent.*;
13 + import static java.util.concurrent.TimeUnit.MILLISECONDS;
14   import java.io.*;
15 + import java.util.*;
16  
17 < public class ReentrantReadWriteLockTest extends TestCase {
14 <    static int HOLD_COUNT_TEST_LIMIT = 20;
15 <    
17 > public class ReentrantReadWriteLockTest extends JSR166TestCase {
18      public static void main(String[] args) {
19 <        junit.textui.TestRunner.run (suite());  
19 >        junit.textui.TestRunner.run(suite());
20      }
19    
21      public static Test suite() {
22 <        return new TestSuite(ReentrantReadWriteLockTest.class);
22 >        return new TestSuite(ReentrantReadWriteLockTest.class);
23      }
24  
25 +    /**
26 +     * A runnable calling lockInterruptibly
27 +     */
28 +    class InterruptibleLockRunnable extends CheckedRunnable {
29 +        final ReentrantReadWriteLock lock;
30 +        InterruptibleLockRunnable(ReentrantReadWriteLock l) { lock = l; }
31 +        public void realRun() throws InterruptedException {
32 +            lock.writeLock().lockInterruptibly();
33 +        }
34 +    }
35  
36 <    private static long SHORT_DELAY_MS = 100;
37 <    private static long MEDIUM_DELAY_MS = 1000;
38 <    private static long LONG_DELAY_MS = 10000;
36 >    /**
37 >     * A runnable calling lockInterruptibly that expects to be
38 >     * interrupted
39 >     */
40 >    class InterruptedLockRunnable extends CheckedInterruptedRunnable {
41 >        final ReentrantReadWriteLock lock;
42 >        InterruptedLockRunnable(ReentrantReadWriteLock l) { lock = l; }
43 >        public void realRun() throws InterruptedException {
44 >            lock.writeLock().lockInterruptibly();
45 >        }
46 >    }
47  
48 <    /*
49 <     * Unlocks an unlocked lock, throws Illegal Monitor State
31 <     *
48 >    /**
49 >     * Subclass to expose protected methods
50       */
51 <    
52 <    public void testIllegalMonitorStateException(){
53 <        ReentrantReadWriteLock rl = new ReentrantReadWriteLock();
54 <        try{
55 <            rl.writeLock().unlock();
56 <            fail("Should of thown Illegal Monitor State Exception");
51 >    static class PublicReentrantReadWriteLock extends ReentrantReadWriteLock {
52 >        PublicReentrantReadWriteLock() { super(); }
53 >        PublicReentrantReadWriteLock(boolean fair) { super(fair); }
54 >        public Thread getOwner() {
55 >            return super.getOwner();
56 >        }
57 >        public Collection<Thread> getQueuedThreads() {
58 >            return super.getQueuedThreads();
59 >        }
60 >        public Collection<Thread> getWaitingThreads(Condition c) {
61 >            return super.getWaitingThreads(c);
62 >        }
63 >    }
64  
65 <        }catch(IllegalMonitorStateException success){}
65 >    /**
66 >     * Releases write lock, checking that it had a hold count of 1.
67 >     */
68 >    void releaseWriteLock(PublicReentrantReadWriteLock lock) {
69 >        ReentrantReadWriteLock.WriteLock writeLock = lock.writeLock();
70 >        assertWriteLockedBy(lock, Thread.currentThread());
71 >        assertEquals(1, lock.getWriteHoldCount());
72 >        writeLock.unlock();
73 >        assertNotWriteLocked(lock);
74      }
75  
76 +    /**
77 +     * Spin-waits until lock.hasQueuedThread(t) becomes true.
78 +     */
79 +    void waitForQueuedThread(PublicReentrantReadWriteLock lock, Thread t) {
80 +        long startTime = System.nanoTime();
81 +        while (!lock.hasQueuedThread(t)) {
82 +            if (millisElapsedSince(startTime) > LONG_DELAY_MS)
83 +                throw new AssertionError("timed out");
84 +            Thread.yield();
85 +        }
86 +        assertTrue(t.isAlive());
87 +        assertTrue(lock.getOwner() != t);
88 +    }
89  
90 +    /**
91 +     * Checks that lock is not write-locked.
92 +     */
93 +    void assertNotWriteLocked(PublicReentrantReadWriteLock lock) {
94 +        assertFalse(lock.isWriteLocked());
95 +        assertFalse(lock.isWriteLockedByCurrentThread());
96 +        assertFalse(lock.writeLock().isHeldByCurrentThread());
97 +        assertNull(lock.getOwner());
98 +        assertEquals(0, lock.getWriteHoldCount());
99 +    }
100  
101 <    public void testInterruptedException(){
102 <        final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
103 <        lock.writeLock().lock();
104 <        Thread t = new Thread(new Runnable() {
105 <                public void run(){
106 <                    try{
107 <                        lock.writeLock().lockInterruptibly();
108 <                        fail("should throw");
109 <                    }catch(InterruptedException success){}
110 <                }
111 <            });
112 <        try {
113 <            t.start();
58 <            t.interrupt();
59 <            lock.writeLock().unlock();
60 <            t.join();
61 <        } catch(Exception e){
62 <            fail("unexpected exception");
63 <        }
64 <    }
65 <
66 <    public void testInterruptedException2(){
67 <        final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
68 <        lock.writeLock().lock();
69 <        Thread t = new Thread(new Runnable() {
70 <                public void run(){
71 <                    try{
72 <                        lock.writeLock().tryLock(1000,TimeUnit.MILLISECONDS);
73 <                        fail("should throw");
74 <                    }catch(InterruptedException success){}
75 <                }
76 <            });
77 <        try {
78 <            t.start();
79 <            t.interrupt();
80 <            lock.writeLock().unlock();
81 <            t.join();
82 <        } catch(Exception e){
83 <            fail("unexpected exception");
84 <        }
101 >    /**
102 >     * Checks that lock is write-locked by the given thread.
103 >     */
104 >    void assertWriteLockedBy(PublicReentrantReadWriteLock lock, Thread t) {
105 >        assertTrue(lock.isWriteLocked());
106 >        assertSame(t, lock.getOwner());
107 >        assertEquals(t == Thread.currentThread(),
108 >                     lock.isWriteLockedByCurrentThread());
109 >        assertEquals(t == Thread.currentThread(),
110 >                     lock.writeLock().isHeldByCurrentThread());
111 >        assertEquals(t == Thread.currentThread(),
112 >                     lock.getWriteHoldCount() > 0);
113 >        assertEquals(0, lock.getReadLockCount());
114      }
115  
116 <    public void testInterruptedException3(){
117 <        final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
118 <        lock.writeLock().lock();
119 <        Thread t = new Thread(new Runnable() {
120 <                public void run(){
92 <                    try{
93 <                        lock.readLock().lockInterruptibly();
94 <                        fail("should throw");
95 <                    }catch(InterruptedException success){}
96 <                }
97 <            });
98 <        try {
99 <            t.start();
100 <            t.interrupt();
101 <            lock.writeLock().unlock();
102 <            t.join();
103 <        } catch(Exception e){
104 <            fail("unexpected exception");
105 <        }
106 <    }
107 <
108 <    public void testInterruptedException4(){
109 <        final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
110 <        lock.writeLock().lock();
111 <        Thread t = new Thread(new Runnable() {
112 <                public void run(){
113 <                    try{
114 <                        lock.readLock().tryLock(1000,TimeUnit.MILLISECONDS);
115 <                        fail("should throw");
116 <                    }catch(InterruptedException success){}
117 <                }
118 <            });
119 <        try {
120 <            t.start();
121 <            t.interrupt();
122 <            t.join();
123 <        } catch(Exception e){
124 <            fail("unexpected exception");
125 <        }
116 >    /**
117 >     * Checks that condition c has no waiters.
118 >     */
119 >    void assertHasNoWaiters(PublicReentrantReadWriteLock lock, Condition c) {
120 >        assertHasWaiters(lock, c, new Thread[] {});
121      }
122  
123 <    
124 <    public void testTryLockWhenLocked() {
125 <        final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
126 <        lock.writeLock().lock();
127 <        Thread t = new Thread(new Runnable() {
128 <                public void run(){
129 <                    assertFalse(lock.writeLock().tryLock());
130 <                }
131 <            });
132 <        try {
133 <            t.start();
134 <            t.join();
123 >    /**
124 >     * Checks that condition c has exactly the given waiter threads.
125 >     */
126 >    void assertHasWaiters(PublicReentrantReadWriteLock lock, Condition c,
127 >                          Thread... threads) {
128 >        lock.writeLock().lock();
129 >        assertEquals(threads.length > 0, lock.hasWaiters(c));
130 >        assertEquals(threads.length, lock.getWaitQueueLength(c));
131 >        assertEquals(threads.length == 0, lock.getWaitingThreads(c).isEmpty());
132 >        assertEquals(threads.length, lock.getWaitingThreads(c).size());
133 >        assertEquals(new HashSet<Thread>(lock.getWaitingThreads(c)),
134 >                     new HashSet<Thread>(Arrays.asList(threads)));
135 >        lock.writeLock().unlock();
136 >    }
137 >
138 >    /**
139 >     * Constructor sets given fairness, and is in unlocked state
140 >     */
141 >    public void testConstructor() {
142 >        PublicReentrantReadWriteLock lock;
143 >
144 >        lock = new PublicReentrantReadWriteLock();
145 >        assertFalse(lock.isFair());
146 >        assertNotWriteLocked(lock);
147 >        assertEquals(0, lock.getReadLockCount());
148 >
149 >        lock = new PublicReentrantReadWriteLock(true);
150 >        assertTrue(lock.isFair());
151 >        assertNotWriteLocked(lock);
152 >        assertEquals(0, lock.getReadLockCount());
153 >
154 >        lock = new PublicReentrantReadWriteLock(false);
155 >        assertFalse(lock.isFair());
156 >        assertNotWriteLocked(lock);
157 >        assertEquals(0, lock.getReadLockCount());
158 >    }
159 >
160 >    /**
161 >     * write-locking and read-locking an unlocked lock succeed
162 >     */
163 >    public void testLock() {
164 >        PublicReentrantReadWriteLock lock = new PublicReentrantReadWriteLock();
165 >        assertNotWriteLocked(lock);
166 >        lock.writeLock().lock();
167 >        assertWriteLockedBy(lock, Thread.currentThread());
168 >        lock.writeLock().unlock();
169 >        assertNotWriteLocked(lock);
170 >        assertEquals(0, lock.getReadLockCount());
171 >        lock.readLock().lock();
172 >        assertNotWriteLocked(lock);
173 >        assertEquals(1, lock.getReadLockCount());
174 >        lock.readLock().unlock();
175 >        assertNotWriteLocked(lock);
176 >        assertEquals(0, lock.getReadLockCount());
177 >    }
178 >
179 >    /**
180 >     * locking an unlocked fair lock succeeds
181 >     */
182 >    public void testFairLock() {
183 >        PublicReentrantReadWriteLock lock = new PublicReentrantReadWriteLock(true);
184 >        assertNotWriteLocked(lock);
185 >        lock.writeLock().lock();
186 >        assertWriteLockedBy(lock, Thread.currentThread());
187 >        lock.writeLock().unlock();
188 >        assertNotWriteLocked(lock);
189 >        assertEquals(0, lock.getReadLockCount());
190 >        lock.readLock().lock();
191 >        assertNotWriteLocked(lock);
192 >        assertEquals(1, lock.getReadLockCount());
193 >        lock.readLock().unlock();
194 >        assertNotWriteLocked(lock);
195 >        assertEquals(0, lock.getReadLockCount());
196 >    }
197 >
198 >    /**
199 >     * getWriteHoldCount returns number of recursive holds
200 >     */
201 >    public void testGetWriteHoldCount() {
202 >        ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
203 >        for (int i = 1; i <= SIZE; i++) {
204 >            lock.writeLock().lock();
205 >            assertEquals(i,lock.getWriteHoldCount());
206 >        }
207 >        for (int i = SIZE; i > 0; i--) {
208              lock.writeLock().unlock();
209 <        } catch(Exception e){
142 <            fail("unexpected exception");
209 >            assertEquals(i-1,lock.getWriteHoldCount());
210          }
211 <    }
211 >    }
212  
213 <    public void testTryLockWhenLocked2() {
214 <        final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
215 <        lock.writeLock().lock();
216 <        Thread t = new Thread(new Runnable() {
217 <                public void run(){
218 <                    assertFalse(lock.readLock().tryLock());
219 <                }
220 <            });
221 <        try {
222 <            t.start();
156 <            t.join();
213 >    /**
214 >     * WriteLock.getHoldCount returns number of recursive holds
215 >     */
216 >    public void testGetHoldCount() {
217 >        ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
218 >        for (int i = 1; i <= SIZE; i++) {
219 >            lock.writeLock().lock();
220 >            assertEquals(i,lock.writeLock().getHoldCount());
221 >        }
222 >        for (int i = SIZE; i > 0; i--) {
223              lock.writeLock().unlock();
224 <        } catch(Exception e){
159 <            fail("unexpected exception");
224 >            assertEquals(i-1,lock.writeLock().getHoldCount());
225          }
226 <    }
226 >    }
227  
228 <    public void testMultipleReadLocks() {
229 <        final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
230 <        lock.readLock().lock();
231 <        Thread t = new Thread(new Runnable() {
232 <                public void run(){
233 <                    assertTrue(lock.readLock().tryLock());
234 <                    lock.readLock().unlock();
235 <                }
236 <            });
237 <        try {
173 <            t.start();
174 <            t.join();
228 >    /**
229 >     * getReadHoldCount returns number of recursive holds
230 >     */
231 >    public void testGetReadHoldCount() {
232 >        ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
233 >        for (int i = 1; i <= SIZE; i++) {
234 >            lock.readLock().lock();
235 >            assertEquals(i,lock.getReadHoldCount());
236 >        }
237 >        for (int i = SIZE; i > 0; i--) {
238              lock.readLock().unlock();
239 <        } catch(Exception e){
177 <            fail("unexpected exception");
239 >            assertEquals(i-1,lock.getReadHoldCount());
240          }
241 <    }
180 <
181 <    public void testWriteAfterMultipleReadLocks() {
182 <        final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
183 <        lock.readLock().lock();
184 <        Thread t1 = new Thread(new Runnable() {
185 <                public void run(){
186 <                    lock.readLock().lock();
187 <                    lock.readLock().unlock();
188 <                }
189 <            });
190 <        Thread t2 = new Thread(new Runnable() {
191 <                public void run(){
192 <                    lock.writeLock().lock();
193 <                    lock.writeLock().unlock();
194 <                }
195 <            });
241 >    }
242  
243 +    /**
244 +     * write-unlocking an unlocked lock throws IllegalMonitorStateException
245 +     */
246 +    public void testWriteUnlock_IllegalMonitorStateException() {
247 +        ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
248          try {
198            t1.start();
199            t2.start();
200            Thread.sleep(SHORT_DELAY_MS);
201            lock.readLock().unlock();
202            t1.join(MEDIUM_DELAY_MS);
203            t2.join(MEDIUM_DELAY_MS);
204            assertTrue(!t1.isAlive());
205            assertTrue(!t2.isAlive());
206          
207        } catch(Exception e){
208            fail("unexpected exception");
209        }
210    }
211
212    public void testReadAfterWriteLock() {
213        final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
214        lock.writeLock().lock();
215        Thread t1 = new Thread(new Runnable() {
216                public void run(){
217                    lock.readLock().lock();
218                    lock.readLock().unlock();
219                }
220            });
221        Thread t2 = new Thread(new Runnable() {
222                public void run(){
223                    lock.readLock().lock();
224                    lock.readLock().unlock();
225                }
226            });
227
228        try {
229            t1.start();
230            t2.start();
231            Thread.sleep(SHORT_DELAY_MS);
249              lock.writeLock().unlock();
250 <            t1.join(MEDIUM_DELAY_MS);
251 <            t2.join(MEDIUM_DELAY_MS);
252 <            assertTrue(!t1.isAlive());
253 <            assertTrue(!t2.isAlive());
254 <          
255 <        } catch(Exception e){
256 <            fail("unexpected exception");
257 <        }
258 <    }
242 <
243 <
244 <    public void testTryLockWhenReadLocked() {
245 <        final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
246 <        lock.readLock().lock();
247 <        Thread t = new Thread(new Runnable() {
248 <                public void run(){
249 <                    assertTrue(lock.readLock().tryLock());
250 <                    lock.readLock().unlock();
251 <                }
252 <            });
250 >            shouldThrow();
251 >        } catch (IllegalMonitorStateException success) {}
252 >    }
253 >
254 >    /**
255 >     * read-unlocking an unlocked lock throws IllegalMonitorStateException
256 >     */
257 >    public void testReadUnlock_IllegalMonitorStateException() {
258 >        ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
259          try {
254            t.start();
255            t.join();
260              lock.readLock().unlock();
261 <        } catch(Exception e){
262 <            fail("unexpected exception");
263 <        }
260 <    }
261 >            shouldThrow();
262 >        } catch (IllegalMonitorStateException success) {}
263 >    }
264  
265 <    
265 >    /**
266 >     * write-lockInterruptibly is interruptible
267 >     */
268 >    public void testWriteLockInterruptibly_Interrupted() throws Exception {
269 >        final PublicReentrantReadWriteLock lock = new PublicReentrantReadWriteLock();
270 >        lock.writeLock().lock();
271 >        Thread t = newStartedThread(new CheckedInterruptedRunnable() {
272 >            public void realRun() throws InterruptedException {
273 >                lock.writeLock().lockInterruptibly();
274 >            }});
275 >
276 >        waitForQueuedThread(lock, t);
277 >        t.interrupt();
278 >        awaitTermination(t);
279 >        releaseWriteLock(lock);
280 >    }
281  
282 <    public void testWriteTryLockWhenReadLocked() {
283 <        final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
284 <        lock.readLock().lock();
285 <        Thread t = new Thread(new Runnable() {
286 <                public void run(){
287 <                    assertFalse(lock.writeLock().tryLock());
288 <                }
289 <            });
290 <        try {
291 <            t.start();
292 <            t.join();
293 <            lock.readLock().unlock();
294 <        } catch(Exception e){
295 <            fail("unexpected exception");
296 <        }
297 <    }
282 >    /**
283 >     * timed write-tryLock is interruptible
284 >     */
285 >    public void testWriteTryLock_Interrupted() throws InterruptedException {
286 >        final PublicReentrantReadWriteLock lock = new PublicReentrantReadWriteLock();
287 >        lock.writeLock().lock();
288 >        Thread t = newStartedThread(new CheckedInterruptedRunnable() {
289 >            public void realRun() throws InterruptedException {
290 >                lock.writeLock().tryLock(LONG_DELAY_MS, MILLISECONDS);
291 >            }});
292 >
293 >        waitForQueuedThread(lock, t);
294 >        t.interrupt();
295 >        awaitTermination(t);
296 >        releaseWriteLock(lock);
297 >    }
298  
299 <    
299 >    /**
300 >     * read-lockInterruptibly is interruptible
301 >     */
302 >    public void testReadLockInterruptibly_Interrupted() throws InterruptedException {
303 >        final PublicReentrantReadWriteLock lock = new PublicReentrantReadWriteLock();
304 >        lock.writeLock().lock();
305 >        Thread t = newStartedThread(new CheckedInterruptedRunnable() {
306 >            public void realRun() throws InterruptedException {
307 >                lock.readLock().lockInterruptibly();
308 >            }});
309 >
310 >        waitForQueuedThread(lock, t);
311 >        t.interrupt();
312 >        awaitTermination(t);
313 >        releaseWriteLock(lock);
314 >    }
315  
316 <    public void testTryLock_Timeout(){
317 <        final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
318 <        lock.writeLock().lock();
319 <        Thread t = new Thread(new Runnable() {
320 <                public void run(){
321 <                    try {
322 <                        assertFalse(lock.writeLock().tryLock(1, TimeUnit.MILLISECONDS));
323 <                    } catch (Exception ex) {
324 <                        fail("unexpected exception");
325 <                    }
326 <                }
327 <            });
328 <        try {
329 <            t.start();
330 <            t.join();
331 <            lock.writeLock().unlock();
299 <        } catch(Exception e){
300 <            fail("unexpected exception");
301 <        }
302 <    }
316 >    /**
317 >     * timed read-tryLock is interruptible
318 >     */
319 >    public void testReadTryLock_Interrupted() throws InterruptedException {
320 >        final PublicReentrantReadWriteLock lock = new PublicReentrantReadWriteLock();
321 >        lock.writeLock().lock();
322 >        Thread t = newStartedThread(new CheckedInterruptedRunnable() {
323 >            public void realRun() throws InterruptedException {
324 >                lock.readLock().tryLock(LONG_DELAY_MS, MILLISECONDS);
325 >            }});
326 >
327 >        waitForQueuedThread(lock, t);
328 >        t.interrupt();
329 >        awaitTermination(t);
330 >        releaseWriteLock(lock);
331 >    }
332  
333 <    public void testTryLock_Timeout2(){
334 <        final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
335 <        lock.writeLock().lock();
336 <        Thread t = new Thread(new Runnable() {
337 <                public void run(){
338 <                    try {
339 <                        assertFalse(lock.readLock().tryLock(1, TimeUnit.MILLISECONDS));
340 <                    } catch (Exception ex) {
341 <                        fail("unexpected exception");
342 <                    }
314 <                }
315 <            });
316 <        try {
317 <            t.start();
318 <            t.join();
319 <            lock.writeLock().unlock();
320 <        } catch(Exception e){
321 <            fail("unexpected exception");
322 <        }
323 <    }
333 >    /**
334 >     * write-tryLock fails if locked
335 >     */
336 >    public void testWriteTryLockWhenLocked() throws InterruptedException {
337 >        final PublicReentrantReadWriteLock lock = new PublicReentrantReadWriteLock();
338 >        lock.writeLock().lock();
339 >        Thread t = newStartedThread(new CheckedRunnable() {
340 >            public void realRun() {
341 >                assertFalse(lock.writeLock().tryLock());
342 >            }});
343  
344 +        awaitTermination(t);
345 +        releaseWriteLock(lock);
346 +    }
347  
348 <    public void testLockInterruptibly() {
349 <        final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
350 <        try {
351 <            lock.writeLock().lockInterruptibly();
352 <        } catch(Exception e) {
353 <            fail("unexpected exception");
354 <        }
355 <        Thread t = new Thread(new Runnable() {
356 <                public void run() {
357 <                    try {
358 <                        lock.writeLock().lockInterruptibly();
359 <                        fail("should throw");
360 <                    }
339 <                    catch(InterruptedException success) {
340 <                    }
341 <                }
342 <            });
343 <        try {
344 <            t.start();
345 <            t.interrupt();
346 <            t.join();
347 <            lock.writeLock().unlock();
348 <        } catch(Exception e){
349 <            fail("unexpected exception");
350 <        }
348 >    /**
349 >     * read-tryLock fails if locked
350 >     */
351 >    public void testReadTryLockWhenLocked() throws InterruptedException {
352 >        final PublicReentrantReadWriteLock lock = new PublicReentrantReadWriteLock();
353 >        lock.writeLock().lock();
354 >        Thread t = newStartedThread(new CheckedRunnable() {
355 >            public void realRun() {
356 >                assertFalse(lock.readLock().tryLock());
357 >            }});
358 >
359 >        awaitTermination(t);
360 >        releaseWriteLock(lock);
361      }
362  
363 <    public void testLockInterruptibly2() {
364 <        final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
365 <        try {
366 <            lock.writeLock().lockInterruptibly();
367 <        } catch(Exception e) {
368 <            fail("unexpected exception");
369 <        }
370 <        Thread t = new Thread(new Runnable() {
371 <                public void run() {
372 <                    try {
373 <                        lock.readLock().lockInterruptibly();
374 <                        fail("should throw");
375 <                    }
376 <                    catch(InterruptedException success) {
377 <                    }
378 <                }
379 <            });
380 <        try {
381 <            t.start();
382 <            t.interrupt();
383 <            t.join();
384 <            lock.writeLock().unlock();
385 <        } catch(Exception e){
386 <            fail("unexpected exception");
387 <        }
363 >    /**
364 >     * Multiple threads can hold a read lock when not write-locked
365 >     */
366 >    public void testMultipleReadLocks() throws InterruptedException {
367 >        final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
368 >        lock.readLock().lock();
369 >        Thread t = newStartedThread(new CheckedRunnable() {
370 >            public void realRun() {
371 >                assertTrue(lock.readLock().tryLock());
372 >                lock.readLock().unlock();
373 >            }});
374 >
375 >        awaitTermination(t);
376 >        lock.readLock().unlock();
377 >    }
378 >
379 >    /**
380 >     * A writelock succeeds only after a reading thread unlocks
381 >     */
382 >    public void testWriteAfterReadLock() throws InterruptedException {
383 >        final PublicReentrantReadWriteLock lock = new PublicReentrantReadWriteLock();
384 >        lock.readLock().lock();
385 >
386 >        Thread t = newStartedThread(new CheckedRunnable() {
387 >            public void realRun() {
388 >                assertEquals(1, lock.getReadLockCount());
389 >                lock.writeLock().lock();
390 >                assertEquals(0, lock.getReadLockCount());
391 >                lock.writeLock().unlock();
392 >            }});
393 >        waitForQueuedThread(lock, t);
394 >        assertNotWriteLocked(lock);
395 >        assertEquals(1, lock.getReadLockCount());
396 >        lock.readLock().unlock();
397 >        assertEquals(0, lock.getReadLockCount());
398 >        awaitTermination(t);
399 >        assertNotWriteLocked(lock);
400 >    }
401 >
402 >    /**
403 >     * A writelock succeeds only after reading threads unlock
404 >     */
405 >    public void testWriteAfterMultipleReadLocks() throws InterruptedException {
406 >        final PublicReentrantReadWriteLock lock = new PublicReentrantReadWriteLock();
407 >        lock.readLock().lock();
408 >        lock.readLock().lock();
409 >        Thread t1 = newStartedThread(new CheckedRunnable() {
410 >            public void realRun() {
411 >                lock.readLock().lock();
412 >                assertEquals(3, lock.getReadLockCount());
413 >                lock.readLock().unlock();
414 >            }});
415 >        awaitTermination(t1);
416 >
417 >        Thread t2 = newStartedThread(new CheckedRunnable() {
418 >            public void realRun() {
419 >                assertEquals(2, lock.getReadLockCount());
420 >                lock.writeLock().lock();
421 >                assertEquals(0, lock.getReadLockCount());
422 >                lock.writeLock().unlock();
423 >            }});
424 >        waitForQueuedThread(lock, t2);
425 >        assertNotWriteLocked(lock);
426 >        assertEquals(2, lock.getReadLockCount());
427 >        lock.readLock().unlock();
428 >        lock.readLock().unlock();
429 >        assertEquals(0, lock.getReadLockCount());
430 >        awaitTermination(t2);
431 >        assertNotWriteLocked(lock);
432 >    }
433 >
434 >    /**
435 >     * A thread that tries to acquire a fair read lock (non-reentrantly)
436 >     * will block if there is a waiting writer thread.
437 >     */
438 >    public void testReaderWriterReaderFairFifo() throws InterruptedException {
439 >        final PublicReentrantReadWriteLock lock = new PublicReentrantReadWriteLock(true);
440 >        final AtomicBoolean t1GotLock = new AtomicBoolean(false);
441 >
442 >        lock.readLock().lock();
443 >        Thread t1 = newStartedThread(new CheckedRunnable() {
444 >            public void realRun() {
445 >                assertEquals(1, lock.getReadLockCount());
446 >                lock.writeLock().lock();
447 >                assertEquals(0, lock.getReadLockCount());
448 >                t1GotLock.set(true);
449 >                lock.writeLock().unlock();
450 >            }});
451 >        waitForQueuedThread(lock, t1);
452 >
453 >        Thread t2 = newStartedThread(new CheckedRunnable() {
454 >            public void realRun() {
455 >                assertEquals(1, lock.getReadLockCount());
456 >                lock.readLock().lock();
457 >                assertEquals(1, lock.getReadLockCount());
458 >                assertTrue(t1GotLock.get());
459 >                lock.readLock().unlock();
460 >            }});
461 >        waitForQueuedThread(lock, t2);
462 >        assertTrue(t1.isAlive());
463 >        assertNotWriteLocked(lock);
464 >        assertEquals(1, lock.getReadLockCount());
465 >        lock.readLock().unlock();
466 >        awaitTermination(t1);
467 >        awaitTermination(t2);
468 >        assertNotWriteLocked(lock);
469 >    }
470 >
471 >    /**
472 >     * Readlocks succeed only after a writing thread unlocks
473 >     */
474 >    public void testReadAfterWriteLock() throws InterruptedException {
475 >        final PublicReentrantReadWriteLock lock = new PublicReentrantReadWriteLock();
476 >        lock.writeLock().lock();
477 >        Thread t1 = newStartedThread(new CheckedRunnable() {
478 >            public void realRun() {
479 >                lock.readLock().lock();
480 >                lock.readLock().unlock();
481 >            }});
482 >        Thread t2 = newStartedThread(new CheckedRunnable() {
483 >            public void realRun() {
484 >                lock.readLock().lock();
485 >                lock.readLock().unlock();
486 >            }});
487 >
488 >        waitForQueuedThread(lock, t1);
489 >        waitForQueuedThread(lock, t2);
490 >        releaseWriteLock(lock);
491 >        awaitTermination(t1);
492 >        awaitTermination(t2);
493 >    }
494 >
495 >    /**
496 >     * Read trylock succeeds if write locked by current thread
497 >     */
498 >    public void testReadHoldingWriteLock() {
499 >        final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
500 >        lock.writeLock().lock();
501 >        assertTrue(lock.readLock().tryLock());
502 >        lock.readLock().unlock();
503 >        lock.writeLock().unlock();
504 >    }
505 >
506 >    /**
507 >     * Read lock succeeds if write locked by current thread even if
508 >     * other threads are waiting for readlock
509 >     */
510 >    public void testReadHoldingWriteLock2() throws InterruptedException {
511 >        final PublicReentrantReadWriteLock lock = new PublicReentrantReadWriteLock();
512 >        lock.writeLock().lock();
513 >        lock.readLock().lock();
514 >        lock.readLock().unlock();
515 >
516 >        Thread t1 = newStartedThread(new CheckedRunnable() {
517 >            public void realRun() {
518 >                lock.readLock().lock();
519 >                lock.readLock().unlock();
520 >            }});
521 >        Thread t2 = newStartedThread(new CheckedRunnable() {
522 >            public void realRun() {
523 >                lock.readLock().lock();
524 >                lock.readLock().unlock();
525 >            }});
526 >
527 >        waitForQueuedThread(lock, t1);
528 >        waitForQueuedThread(lock, t2);
529 >        assertWriteLockedBy(lock, Thread.currentThread());
530 >        lock.readLock().lock();
531 >        lock.readLock().unlock();
532 >        releaseWriteLock(lock);
533 >        awaitTermination(t1);
534 >        awaitTermination(t2);
535 >    }
536 >
537 >    /**
538 >     * Read lock succeeds if write locked by current thread even if
539 >     * other threads are waiting for writelock
540 >     */
541 >    public void testReadHoldingWriteLock3() throws InterruptedException {
542 >        final PublicReentrantReadWriteLock lock = new PublicReentrantReadWriteLock();
543 >        lock.writeLock().lock();
544 >        lock.readLock().lock();
545 >        lock.readLock().unlock();
546 >
547 >        Thread t1 = newStartedThread(new CheckedRunnable() {
548 >            public void realRun() {
549 >                lock.writeLock().lock();
550 >                lock.writeLock().unlock();
551 >            }});
552 >        Thread t2 = newStartedThread(new CheckedRunnable() {
553 >            public void realRun() {
554 >                lock.writeLock().lock();
555 >                lock.writeLock().unlock();
556 >            }});
557 >
558 >        waitForQueuedThread(lock, t1);
559 >        waitForQueuedThread(lock, t2);
560 >        assertWriteLockedBy(lock, Thread.currentThread());
561 >        lock.readLock().lock();
562 >        lock.readLock().unlock();
563 >        releaseWriteLock(lock);
564 >        awaitTermination(t1);
565 >        awaitTermination(t2);
566 >    }
567 >
568 >    /**
569 >     * Write lock succeeds if write locked by current thread even if
570 >     * other threads are waiting for writelock
571 >     */
572 >    public void testWriteHoldingWriteLock4() throws InterruptedException {
573 >        final PublicReentrantReadWriteLock lock = new PublicReentrantReadWriteLock();
574 >        lock.writeLock().lock();
575 >        lock.writeLock().lock();
576 >        lock.writeLock().unlock();
577 >
578 >        Thread t1 = newStartedThread(new CheckedRunnable() {
579 >            public void realRun() {
580 >                lock.writeLock().lock();
581 >                lock.writeLock().unlock();
582 >            }});
583 >        Thread t2 = newStartedThread(new CheckedRunnable() {
584 >            public void realRun() {
585 >                lock.writeLock().lock();
586 >                lock.writeLock().unlock();
587 >            }});
588 >
589 >        waitForQueuedThread(lock, t1);
590 >        waitForQueuedThread(lock, t2);
591 >        assertWriteLockedBy(lock, Thread.currentThread());
592 >        assertEquals(1, lock.getWriteHoldCount());
593 >        lock.writeLock().lock();
594 >        assertWriteLockedBy(lock, Thread.currentThread());
595 >        assertEquals(2, lock.getWriteHoldCount());
596 >        lock.writeLock().unlock();
597 >        releaseWriteLock(lock);
598 >        awaitTermination(t1);
599 >        awaitTermination(t2);
600 >    }
601 >
602 >    /**
603 >     * Fair Read trylock succeeds if write locked by current thread
604 >     */
605 >    public void testReadHoldingWriteLockFair() {
606 >        final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(true);
607 >        lock.writeLock().lock();
608 >        assertTrue(lock.readLock().tryLock());
609 >        lock.readLock().unlock();
610 >        lock.writeLock().unlock();
611 >    }
612 >
613 >    /**
614 >     * Fair Read lock succeeds if write locked by current thread even if
615 >     * other threads are waiting for readlock
616 >     */
617 >    public void testReadHoldingWriteLockFair2() throws InterruptedException {
618 >        final PublicReentrantReadWriteLock lock = new PublicReentrantReadWriteLock(true);
619 >        lock.writeLock().lock();
620 >        lock.readLock().lock();
621 >        lock.readLock().unlock();
622 >
623 >        Thread t1 = newStartedThread(new CheckedRunnable() {
624 >            public void realRun() {
625 >                lock.readLock().lock();
626 >                lock.readLock().unlock();
627 >            }});
628 >        Thread t2 = newStartedThread(new CheckedRunnable() {
629 >            public void realRun() {
630 >                lock.readLock().lock();
631 >                lock.readLock().unlock();
632 >            }});
633 >
634 >        waitForQueuedThread(lock, t1);
635 >        waitForQueuedThread(lock, t2);
636 >        assertWriteLockedBy(lock, Thread.currentThread());
637 >        lock.readLock().lock();
638 >        lock.readLock().unlock();
639 >        releaseWriteLock(lock);
640 >        awaitTermination(t1);
641 >        awaitTermination(t2);
642 >    }
643 >
644 >    /**
645 >     * Fair Read lock succeeds if write locked by current thread even if
646 >     * other threads are waiting for writelock
647 >     */
648 >    public void testReadHoldingWriteLockFair3() throws InterruptedException {
649 >        final PublicReentrantReadWriteLock lock = new PublicReentrantReadWriteLock(true);
650 >        lock.writeLock().lock();
651 >        lock.readLock().lock();
652 >        lock.readLock().unlock();
653 >
654 >        Thread t1 = newStartedThread(new CheckedRunnable() {
655 >            public void realRun() {
656 >                lock.writeLock().lock();
657 >                lock.writeLock().unlock();
658 >            }});
659 >        Thread t2 = newStartedThread(new CheckedRunnable() {
660 >            public void realRun() {
661 >                lock.writeLock().lock();
662 >                lock.writeLock().unlock();
663 >            }});
664 >
665 >        waitForQueuedThread(lock, t1);
666 >        waitForQueuedThread(lock, t2);
667 >        assertWriteLockedBy(lock, Thread.currentThread());
668 >        lock.readLock().lock();
669 >        lock.readLock().unlock();
670 >        releaseWriteLock(lock);
671 >        awaitTermination(t1);
672 >        awaitTermination(t2);
673 >    }
674 >
675 >    /**
676 >     * Fair Write lock succeeds if write locked by current thread even if
677 >     * other threads are waiting for writelock
678 >     */
679 >    public void testWriteHoldingWriteLockFair4() throws InterruptedException {
680 >        final PublicReentrantReadWriteLock lock = new PublicReentrantReadWriteLock(true);
681 >        lock.writeLock().lock();
682 >        Thread t1 = newStartedThread(new CheckedRunnable() {
683 >            public void realRun() {
684 >                lock.writeLock().lock();
685 >                lock.writeLock().unlock();
686 >            }});
687 >        Thread t2 = newStartedThread(new CheckedRunnable() {
688 >            public void realRun() {
689 >                lock.writeLock().lock();
690 >                lock.writeLock().unlock();
691 >            }});
692 >
693 >        waitForQueuedThread(lock, t1);
694 >        waitForQueuedThread(lock, t2);
695 >        assertWriteLockedBy(lock, Thread.currentThread());
696 >        assertEquals(1, lock.getWriteHoldCount());
697 >        lock.writeLock().lock();
698 >        assertEquals(2, lock.getWriteHoldCount());
699 >        lock.writeLock().unlock();
700 >        lock.writeLock().lock();
701 >        lock.writeLock().unlock();
702 >        releaseWriteLock(lock);
703 >        awaitTermination(t1);
704 >        awaitTermination(t2);
705 >    }
706 >
707 >    /**
708 >     * Read tryLock succeeds if readlocked but not writelocked
709 >     */
710 >    public void testTryLockWhenReadLocked() throws InterruptedException {
711 >        final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
712 >        lock.readLock().lock();
713 >        Thread t = newStartedThread(new CheckedRunnable() {
714 >            public void realRun() {
715 >                assertTrue(lock.readLock().tryLock());
716 >                lock.readLock().unlock();
717 >            }});
718 >
719 >        awaitTermination(t);
720 >        lock.readLock().unlock();
721 >    }
722 >
723 >    /**
724 >     * write tryLock fails when readlocked
725 >     */
726 >    public void testWriteTryLockWhenReadLocked() throws InterruptedException {
727 >        final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
728 >        lock.readLock().lock();
729 >        Thread t = newStartedThread(new CheckedRunnable() {
730 >            public void realRun() {
731 >                assertFalse(lock.writeLock().tryLock());
732 >            }});
733 >
734 >        awaitTermination(t);
735 >        lock.readLock().unlock();
736 >    }
737 >
738 >    /**
739 >     * Fair Read tryLock succeeds if readlocked but not writelocked
740 >     */
741 >    public void testTryLockWhenReadLockedFair() throws InterruptedException {
742 >        final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(true);
743 >        lock.readLock().lock();
744 >        Thread t = newStartedThread(new CheckedRunnable() {
745 >            public void realRun() {
746 >                assertTrue(lock.readLock().tryLock());
747 >                lock.readLock().unlock();
748 >            }});
749 >
750 >        awaitTermination(t);
751 >        lock.readLock().unlock();
752 >    }
753 >
754 >    /**
755 >     * Fair write tryLock fails when readlocked
756 >     */
757 >    public void testWriteTryLockWhenReadLockedFair() throws InterruptedException {
758 >        final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(true);
759 >        lock.readLock().lock();
760 >        Thread t = newStartedThread(new CheckedRunnable() {
761 >            public void realRun() {
762 >                assertFalse(lock.writeLock().tryLock());
763 >            }});
764 >
765 >        awaitTermination(t);
766 >        lock.readLock().unlock();
767 >    }
768 >
769 >    /**
770 >     * write timed tryLock times out if locked
771 >     */
772 >    public void testWriteTryLock_Timeout() throws InterruptedException {
773 >        final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
774 >        lock.writeLock().lock();
775 >        Thread t = newStartedThread(new CheckedRunnable() {
776 >            public void realRun() throws InterruptedException {
777 >                assertFalse(lock.writeLock().tryLock(1, MILLISECONDS));
778 >            }});
779 >
780 >        awaitTermination(t);
781 >        assertTrue(lock.writeLock().isHeldByCurrentThread());
782 >        lock.writeLock().unlock();
783 >    }
784 >
785 >    /**
786 >     * read timed tryLock times out if write-locked
787 >     */
788 >    public void testReadTryLock_Timeout() throws InterruptedException {
789 >        final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
790 >        lock.writeLock().lock();
791 >        Thread t = newStartedThread(new CheckedRunnable() {
792 >            public void realRun() throws InterruptedException {
793 >                assertFalse(lock.readLock().tryLock(1, MILLISECONDS));
794 >            }});
795 >
796 >        awaitTermination(t);
797 >        assertTrue(lock.writeLock().isHeldByCurrentThread());
798 >        lock.writeLock().unlock();
799 >    }
800 >
801 >    /**
802 >     * write lockInterruptibly succeeds if lock free else is interruptible
803 >     */
804 >    public void testWriteLockInterruptibly() throws InterruptedException {
805 >        final PublicReentrantReadWriteLock lock = new PublicReentrantReadWriteLock();
806 >        lock.writeLock().lockInterruptibly();
807 >        Thread t = newStartedThread(new CheckedInterruptedRunnable() {
808 >            public void realRun() throws InterruptedException {
809 >                lock.writeLock().lockInterruptibly();
810 >            }});
811 >
812 >        waitForQueuedThread(lock, t);
813 >        t.interrupt();
814 >        awaitTermination(t);
815 >        releaseWriteLock(lock);
816 >    }
817 >
818 >    /**
819 >     * read lockInterruptibly succeeds if lock free else is interruptible
820 >     */
821 >    public void testReadLockInterruptibly() throws InterruptedException {
822 >        final PublicReentrantReadWriteLock lock = new PublicReentrantReadWriteLock();
823 >        lock.writeLock().lockInterruptibly();
824 >        Thread t = newStartedThread(new CheckedInterruptedRunnable() {
825 >            public void realRun() throws InterruptedException {
826 >                lock.readLock().lockInterruptibly();
827 >            }});
828 >
829 >        waitForQueuedThread(lock, t);
830 >        t.interrupt();
831 >        awaitTermination(t);
832 >        releaseWriteLock(lock);
833      }
834  
835 <    public void testAwait_IllegalMonitor() {
836 <        final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();      
835 >    /**
836 >     * Calling await without holding lock throws IllegalMonitorStateException
837 >     */
838 >    public void testAwait_IllegalMonitor() throws InterruptedException {
839 >        final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
840          final Condition c = lock.writeLock().newCondition();
841          try {
842              c.await();
843 <            fail("should throw");
844 <        }
845 <        catch (IllegalMonitorStateException success) {
846 <        }
847 <        catch (Exception ex) {
848 <            fail("should throw IMSE");
849 <        }
843 >            shouldThrow();
844 >        } catch (IllegalMonitorStateException success) {}
845 >        try {
846 >            c.await(LONG_DELAY_MS, MILLISECONDS);
847 >            shouldThrow();
848 >        } catch (IllegalMonitorStateException success) {}
849 >        try {
850 >            c.awaitNanos(100);
851 >            shouldThrow();
852 >        } catch (IllegalMonitorStateException success) {}
853 >        try {
854 >            c.awaitUninterruptibly();
855 >            shouldThrow();
856 >        } catch (IllegalMonitorStateException success) {}
857      }
858  
859 +    /**
860 +     * Calling signal without holding lock throws IllegalMonitorStateException
861 +     */
862      public void testSignal_IllegalMonitor() {
863 <        final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();      
863 >        final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
864          final Condition c = lock.writeLock().newCondition();
865          try {
866              c.signal();
867 <            fail("should throw");
868 <        }
401 <        catch (IllegalMonitorStateException success) {
402 <        }
403 <        catch (Exception ex) {
404 <            fail("should throw IMSE");
405 <        }
867 >            shouldThrow();
868 >        } catch (IllegalMonitorStateException success) {}
869      }
870  
871 <    public void testAwaitNanos_Timeout() {
872 <        final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();      
871 >    /**
872 >     * Calling signalAll without holding lock throws IllegalMonitorStateException
873 >     */
874 >    public void testSignalAll_IllegalMonitor() {
875 >        final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
876          final Condition c = lock.writeLock().newCondition();
877          try {
878 <            lock.writeLock().lock();
879 <            long t = c.awaitNanos(100);
880 <            assertTrue(t <= 0);
415 <            lock.writeLock().unlock();
416 <        }
417 <        catch (Exception ex) {
418 <            fail("unexpected exception");
419 <        }
878 >            c.signalAll();
879 >            shouldThrow();
880 >        } catch (IllegalMonitorStateException success) {}
881      }
882  
883 <    public void testAwait_Timeout() {
884 <        final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();      
883 >    /**
884 >     * awaitNanos without a signal times out
885 >     */
886 >    public void testAwaitNanos_Timeout() throws InterruptedException {
887 >        final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
888          final Condition c = lock.writeLock().newCondition();
889 <        try {
890 <            lock.writeLock().lock();
891 <            assertFalse(c.await(10, TimeUnit.MILLISECONDS));
892 <            lock.writeLock().unlock();
893 <        }
894 <        catch (Exception ex) {
895 <            fail("unexpected exception");
896 <        }
889 >        lock.writeLock().lock();
890 >        long startTime = System.nanoTime();
891 >        long timeoutMillis = 10;
892 >        long timeoutNanos = MILLISECONDS.toNanos(timeoutMillis);
893 >        long nanosRemaining = c.awaitNanos(timeoutNanos);
894 >        assertTrue(nanosRemaining <= 0);
895 >        assertTrue(millisElapsedSince(startTime) >= timeoutMillis);
896 >        lock.writeLock().unlock();
897      }
898  
899 <    public void testAwaitUntil_Timeout() {
900 <        final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();      
899 >    /**
900 >     * timed await without a signal times out
901 >     */
902 >    public void testAwait_Timeout() throws InterruptedException {
903 >        final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
904          final Condition c = lock.writeLock().newCondition();
905 <        try {
906 <            lock.writeLock().lock();
907 <            java.util.Date d = new java.util.Date();
908 <            assertFalse(c.awaitUntil(new java.util.Date(d.getTime() + 10)));
909 <            lock.writeLock().unlock();
910 <        }
444 <        catch (Exception ex) {
445 <            fail("unexpected exception");
446 <        }
905 >        lock.writeLock().lock();
906 >        long startTime = System.nanoTime();
907 >        long timeoutMillis = 10;
908 >        assertFalse(c.await(timeoutMillis, MILLISECONDS));
909 >        assertTrue(millisElapsedSince(startTime) >= timeoutMillis);
910 >        lock.writeLock().unlock();
911      }
912  
913 <    public void testAwait() {
914 <        final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();      
913 >    /**
914 >     * awaitUntil without a signal times out
915 >     */
916 >    public void testAwaitUntil_Timeout() throws InterruptedException {
917 >        final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
918          final Condition c = lock.writeLock().newCondition();
919 <        Thread t = new Thread(new Runnable() {
920 <                public void run() {
921 <                    try {
922 <                        lock.writeLock().lock();
923 <                        c.await();
457 <                        lock.writeLock().unlock();
458 <                    }
459 <                    catch(InterruptedException e) {
460 <                        fail("unexpected exception");
461 <                    }
462 <                }
463 <            });
919 >        lock.writeLock().lock();
920 >        java.util.Date d = new java.util.Date();
921 >        assertFalse(c.awaitUntil(new java.util.Date(d.getTime() + 10)));
922 >        lock.writeLock().unlock();
923 >    }
924  
925 <        try {
926 <            t.start();
927 <            Thread.sleep(SHORT_DELAY_MS);
928 <            lock.writeLock().lock();
929 <            c.signal();
930 <            lock.writeLock().unlock();
931 <            t.join(SHORT_DELAY_MS);
932 <            assertFalse(t.isAlive());
933 <        }
934 <        catch (Exception ex) {
935 <            fail("unexpected exception");
936 <        }
925 >    /**
926 >     * await returns when signalled
927 >     */
928 >    public void testAwait() throws InterruptedException {
929 >        final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
930 >        final Condition c = lock.writeLock().newCondition();
931 >        final CountDownLatch locked = new CountDownLatch(1);
932 >        Thread t = newStartedThread(new CheckedRunnable() {
933 >            public void realRun() throws InterruptedException {
934 >                lock.writeLock().lock();
935 >                locked.countDown();
936 >                c.await();
937 >                lock.writeLock().unlock();
938 >            }});
939 >
940 >        locked.await();
941 >        lock.writeLock().lock();
942 >        c.signal();
943 >        assertTrue(t.isAlive());
944 >        lock.writeLock().unlock();
945 >        awaitTermination(t);
946 >    }
947 >
948 >    /**
949 >     * awaitUninterruptibly doesn't abort on interrupt
950 >     */
951 >    public void testAwaitUninterruptibly() throws InterruptedException {
952 >        final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
953 >        final Condition c = lock.writeLock().newCondition();
954 >        final CountDownLatch locked = new CountDownLatch(1);
955 >        final AtomicBoolean canAwake = new AtomicBoolean(false);
956 >        Thread t = newStartedThread(new CheckedRunnable() {
957 >            public void realRun() {
958 >                lock.writeLock().lock();
959 >                locked.countDown();
960 >                c.awaitUninterruptibly();
961 >                assertTrue(Thread.interrupted());
962 >                lock.writeLock().unlock();
963 >            }});
964 >
965 >        locked.await();
966 >        lock.writeLock().lock();
967 >        lock.writeLock().unlock();
968 >        t.interrupt();
969 >        t.join(10);
970 >        assertTrue(t.isAlive());
971 >        lock.writeLock().lock();
972 >        c.signal();
973 >        lock.writeLock().unlock();
974 >        awaitTermination(t);
975      }
976  
977 <    public void testAwaitUninterruptibly() {
978 <        final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();      
977 >    /**
978 >     * await is interruptible
979 >     */
980 >    public void testAwait_Interrupt() throws InterruptedException {
981 >        final PublicReentrantReadWriteLock lock = new PublicReentrantReadWriteLock();
982          final Condition c = lock.writeLock().newCondition();
983 <        Thread t = new Thread(new Runnable() {
984 <                public void run() {
985 <                    lock.writeLock().lock();
986 <                    c.awaitUninterruptibly();
983 >        final CountDownLatch locked = new CountDownLatch(1);
984 >        Thread t = newStartedThread(new CheckedInterruptedRunnable() {
985 >            public void realRun() throws InterruptedException {
986 >                lock.writeLock().lock();
987 >                assertWriteLockedBy(lock, Thread.currentThread());
988 >                assertHasNoWaiters(lock, c);
989 >                locked.countDown();
990 >                try {
991 >                    c.await();
992 >                } finally {
993 >                    assertWriteLockedBy(lock, Thread.currentThread());
994 >                    assertHasNoWaiters(lock, c);
995                      lock.writeLock().unlock();
996 <                }
997 <            });
996 >                    assertFalse(Thread.interrupted());
997 >                }
998 >            }});
999 >
1000 >        locked.await();
1001 >        assertHasWaiters(lock, c, t);
1002 >        t.interrupt();
1003 >        awaitTermination(t);
1004 >        assertNotWriteLocked(lock);
1005 >    }
1006  
1007 <        try {
1008 <            t.start();
1009 <            Thread.sleep(SHORT_DELAY_MS);
1010 <            t.interrupt();
1011 <            lock.writeLock().lock();
1012 <            c.signal();
1013 <            lock.writeLock().unlock();
1014 <            t.join(SHORT_DELAY_MS);
1015 <            assertFalse(t.isAlive());
1016 <        }
1017 <        catch (Exception ex) {
1018 <            fail("unexpected exception");
1019 <        }
1007 >    /**
1008 >     * awaitNanos is interruptible
1009 >     */
1010 >    public void testAwaitNanos_Interrupt() throws InterruptedException {
1011 >        final PublicReentrantReadWriteLock lock = new PublicReentrantReadWriteLock();
1012 >        final Condition c = lock.writeLock().newCondition();
1013 >        final CountDownLatch locked = new CountDownLatch(1);
1014 >        Thread t = newStartedThread(new CheckedInterruptedRunnable() {
1015 >            public void realRun() throws InterruptedException {
1016 >                lock.writeLock().lock();
1017 >                assertWriteLockedBy(lock, Thread.currentThread());
1018 >                assertHasNoWaiters(lock, c);
1019 >                locked.countDown();
1020 >                try {
1021 >                    c.awaitNanos(MILLISECONDS.toNanos(LONG_DELAY_MS));
1022 >                } finally {
1023 >                    assertWriteLockedBy(lock, Thread.currentThread());
1024 >                    assertHasNoWaiters(lock, c);
1025 >                    lock.writeLock().unlock();
1026 >                    assertFalse(Thread.interrupted());
1027 >                }
1028 >            }});
1029 >
1030 >        locked.await();
1031 >        assertHasWaiters(lock, c, t);
1032 >        t.interrupt();
1033 >        awaitTermination(t);
1034 >        assertNotWriteLocked(lock);
1035      }
1036  
1037 <    public void testAwait_Interrupt() {
1038 <        final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();      
1039 <        final Condition c = lock.writeLock().newCondition();
1040 <        Thread t = new Thread(new Runnable() {
1041 <                public void run() {
1042 <                    try {
1043 <                        lock.writeLock().lock();
1044 <                        c.await();
1045 <                        lock.writeLock().unlock();
1046 <                        fail("should throw");
1047 <                    }
1048 <                    catch(InterruptedException success) {
1049 <                    }
1050 <                }
1051 <            });
1052 <
1053 <        try {
1054 <            t.start();
1055 <            Thread.sleep(SHORT_DELAY_MS);
1056 <            t.interrupt();
1057 <            t.join(SHORT_DELAY_MS);
1058 <            assertFalse(t.isAlive());
1059 <        }
1060 <        catch (Exception ex) {
1061 <            fail("unexpected exception");
1062 <        }
1063 <    }
1064 <
1065 <    public void testAwaitNanos_Interrupt() {
534 <        final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();      
535 <        final Condition c = lock.writeLock().newCondition();
536 <        Thread t = new Thread(new Runnable() {
537 <                public void run() {
538 <                    try {
539 <                        lock.writeLock().lock();
540 <                        c.awaitNanos(SHORT_DELAY_MS * 2 * 1000000);
541 <                        lock.writeLock().unlock();
542 <                        fail("should throw");
543 <                    }
544 <                    catch(InterruptedException success) {
545 <                    }
546 <                }
547 <            });
548 <
549 <        try {
550 <            t.start();
551 <            Thread.sleep(SHORT_DELAY_MS);
552 <            t.interrupt();
553 <            t.join(SHORT_DELAY_MS);
554 <            assertFalse(t.isAlive());
555 <        }
556 <        catch (Exception ex) {
557 <            fail("unexpected exception");
558 <        }
559 <    }
560 <
561 <    public void testAwaitUntil_Interrupt() {
562 <        final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();      
563 <        final Condition c = lock.writeLock().newCondition();
564 <        Thread t = new Thread(new Runnable() {
565 <                public void run() {
566 <                    try {
567 <                        lock.writeLock().lock();
568 <                        java.util.Date d = new java.util.Date();
569 <                        c.awaitUntil(new java.util.Date(d.getTime() + 10000));
570 <                        lock.writeLock().unlock();
571 <                        fail("should throw");
572 <                    }
573 <                    catch(InterruptedException success) {
574 <                    }
575 <                }
576 <            });
577 <
578 <        try {
579 <            t.start();
580 <            Thread.sleep(SHORT_DELAY_MS);
581 <            t.interrupt();
582 <            t.join(SHORT_DELAY_MS);
583 <            assertFalse(t.isAlive());
584 <        }
585 <        catch (Exception ex) {
586 <            fail("unexpected exception");
587 <        }
588 <    }
589 <
590 <    public void testSignalAll() {
591 <        final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();      
592 <        final Condition c = lock.writeLock().newCondition();
593 <        Thread t1 = new Thread(new Runnable() {
594 <                public void run() {
595 <                    try {
596 <                        lock.writeLock().lock();
597 <                        c.await();
598 <                        lock.writeLock().unlock();
599 <                    }
600 <                    catch(InterruptedException e) {
601 <                        fail("unexpected exception");
602 <                    }
603 <                }
604 <            });
605 <
606 <        Thread t2 = new Thread(new Runnable() {
607 <                public void run() {
608 <                    try {
609 <                        lock.writeLock().lock();
610 <                        c.await();
611 <                        lock.writeLock().unlock();
612 <                    }
613 <                    catch(InterruptedException e) {
614 <                        fail("unexpected exception");
615 <                    }
616 <                }
617 <            });
618 <
619 <        try {
620 <            t1.start();
621 <            t2.start();
622 <            Thread.sleep(SHORT_DELAY_MS);
623 <            lock.writeLock().lock();
624 <            c.signalAll();
625 <            lock.writeLock().unlock();
626 <            t1.join(SHORT_DELAY_MS);
627 <            t2.join(SHORT_DELAY_MS);
628 <            assertFalse(t1.isAlive());
629 <            assertFalse(t2.isAlive());
630 <        }
631 <        catch (Exception ex) {
632 <            fail("unexpected exception");
633 <        }
1037 >    /**
1038 >     * awaitUntil is interruptible
1039 >     */
1040 >    public void testAwaitUntil_Interrupt() throws InterruptedException {
1041 >        final PublicReentrantReadWriteLock lock = new PublicReentrantReadWriteLock();
1042 >        final Condition c = lock.writeLock().newCondition();
1043 >        final CountDownLatch locked = new CountDownLatch(1);
1044 >        Thread t = newStartedThread(new CheckedInterruptedRunnable() {
1045 >            public void realRun() throws InterruptedException {
1046 >                lock.writeLock().lock();
1047 >                assertWriteLockedBy(lock, Thread.currentThread());
1048 >                assertHasNoWaiters(lock, c);
1049 >                locked.countDown();
1050 >                java.util.Date d = new java.util.Date();
1051 >                try {
1052 >                    c.awaitUntil(new java.util.Date(d.getTime() + 10000));
1053 >                } finally {
1054 >                    assertWriteLockedBy(lock, Thread.currentThread());
1055 >                    assertHasNoWaiters(lock, c);
1056 >                    lock.writeLock().unlock();
1057 >                    assertFalse(Thread.interrupted());
1058 >                }
1059 >            }});
1060 >
1061 >        locked.await();
1062 >        assertHasWaiters(lock, c, t);
1063 >        t.interrupt();
1064 >        awaitTermination(t);
1065 >        assertNotWriteLocked(lock);
1066      }
1067  
1068 <    public void testSerialization() {
1068 >    /**
1069 >     * signalAll wakes up all threads
1070 >     */
1071 >    public void testSignalAll() throws InterruptedException {
1072 >        final PublicReentrantReadWriteLock lock = new PublicReentrantReadWriteLock();
1073 >        final Condition c = lock.writeLock().newCondition();
1074 >        final CountDownLatch locked = new CountDownLatch(2);
1075 >        final Lock writeLock = lock.writeLock();
1076 >        Thread t1 = newStartedThread(new CheckedRunnable() {
1077 >            public void realRun() throws InterruptedException {
1078 >                writeLock.lock();
1079 >                locked.countDown();
1080 >                c.await();
1081 >                writeLock.unlock();
1082 >            }});
1083 >
1084 >        Thread t2 = newStartedThread(new CheckedRunnable() {
1085 >            public void realRun() throws InterruptedException {
1086 >                writeLock.lock();
1087 >                locked.countDown();
1088 >                c.await();
1089 >                writeLock.unlock();
1090 >            }});
1091 >
1092 >        locked.await();
1093 >        writeLock.lock();
1094 >        assertHasWaiters(lock, c, t1, t2);
1095 >        c.signalAll();
1096 >        assertHasNoWaiters(lock, c);
1097 >        writeLock.unlock();
1098 >        awaitTermination(t1);
1099 >        awaitTermination(t2);
1100 >    }
1101 >
1102 >    /**
1103 >     * signal wakes up waiting threads in FIFO order.
1104 >     */
1105 >    public void testSignalWakesFifo() throws InterruptedException {
1106 >        final PublicReentrantReadWriteLock lock = new PublicReentrantReadWriteLock();
1107 >        final Condition c = lock.writeLock().newCondition();
1108 >        final CountDownLatch locked1 = new CountDownLatch(1);
1109 >        final CountDownLatch locked2 = new CountDownLatch(1);
1110 >        final Lock writeLock = lock.writeLock();
1111 >        Thread t1 = newStartedThread(new CheckedRunnable() {
1112 >            public void realRun() throws InterruptedException {
1113 >                writeLock.lock();
1114 >                locked1.countDown();
1115 >                c.await();
1116 >                writeLock.unlock();
1117 >            }});
1118 >
1119 >        locked1.await();
1120 >
1121 >        Thread t2 = newStartedThread(new CheckedRunnable() {
1122 >            public void realRun() throws InterruptedException {
1123 >                writeLock.lock();
1124 >                locked2.countDown();
1125 >                c.await();
1126 >                writeLock.unlock();
1127 >            }});
1128 >
1129 >        locked2.await();
1130 >
1131 >        writeLock.lock();
1132 >        assertHasWaiters(lock, c, t1, t2);
1133 >        assertFalse(lock.hasQueuedThreads());
1134 >        c.signal();
1135 >        assertHasWaiters(lock, c, t2);
1136 >        assertTrue(lock.hasQueuedThread(t1));
1137 >        assertFalse(lock.hasQueuedThread(t2));
1138 >        c.signal();
1139 >        assertHasNoWaiters(lock, c);
1140 >        assertTrue(lock.hasQueuedThread(t1));
1141 >        assertTrue(lock.hasQueuedThread(t2));
1142 >        writeLock.unlock();
1143 >        awaitTermination(t1);
1144 >        awaitTermination(t2);
1145 >    }
1146 >
1147 >    /**
1148 >     * A serialized lock deserializes as unlocked
1149 >     */
1150 >    public void testSerialization() throws Exception {
1151          ReentrantReadWriteLock l = new ReentrantReadWriteLock();
1152          l.readLock().lock();
1153          l.readLock().unlock();
1154  
1155 +        ByteArrayOutputStream bout = new ByteArrayOutputStream(10000);
1156 +        ObjectOutputStream out = new ObjectOutputStream(new BufferedOutputStream(bout));
1157 +        out.writeObject(l);
1158 +        out.close();
1159 +
1160 +        ByteArrayInputStream bin = new ByteArrayInputStream(bout.toByteArray());
1161 +        ObjectInputStream in = new ObjectInputStream(new BufferedInputStream(bin));
1162 +        ReentrantReadWriteLock r = (ReentrantReadWriteLock) in.readObject();
1163 +        r.readLock().lock();
1164 +        r.readLock().unlock();
1165 +    }
1166 +
1167 +    /**
1168 +     * hasQueuedThreads reports whether there are waiting threads
1169 +     */
1170 +    public void testhasQueuedThreads() throws InterruptedException {
1171 +        final PublicReentrantReadWriteLock lock = new PublicReentrantReadWriteLock();
1172 +        Thread t1 = new Thread(new InterruptedLockRunnable(lock));
1173 +        Thread t2 = new Thread(new InterruptibleLockRunnable(lock));
1174 +        assertFalse(lock.hasQueuedThreads());
1175 +        lock.writeLock().lock();
1176 +        assertFalse(lock.hasQueuedThreads());
1177 +        long startTime = System.nanoTime();
1178 +        t1.start();
1179 +        waitForQueuedThread(lock, t1);
1180 +        t2.start();
1181 +        waitForQueuedThread(lock, t2);
1182 +        assertTrue(lock.hasQueuedThreads());
1183 +        t1.interrupt();
1184 +        awaitTermination(t1);
1185 +        assertTrue(lock.hasQueuedThreads());
1186 +        lock.writeLock().unlock();
1187 +        awaitTermination(t2);
1188 +        assertFalse(lock.hasQueuedThreads());
1189 +    }
1190 +
1191 +    /**
1192 +     * hasQueuedThread(null) throws NPE
1193 +     */
1194 +    public void testHasQueuedThreadNPE() {
1195 +        final ReentrantReadWriteLock sync = new ReentrantReadWriteLock();
1196          try {
1197 <            ByteArrayOutputStream bout = new ByteArrayOutputStream(10000);
1198 <            ObjectOutputStream out = new ObjectOutputStream(new BufferedOutputStream(bout));
1199 <            out.writeObject(l);
1200 <            out.close();
1201 <
1202 <            ByteArrayInputStream bin = new ByteArrayInputStream(bout.toByteArray());
1203 <            ObjectInputStream in = new ObjectInputStream(new BufferedInputStream(bin));
1204 <            ReentrantReadWriteLock r = (ReentrantReadWriteLock) in.readObject();
1205 <            r.readLock().lock();
1206 <            r.readLock().unlock();
1207 <        } catch(Exception e){
1208 <            e.printStackTrace();
1209 <            fail("unexpected exception");
1210 <        }
1197 >            sync.hasQueuedThread(null);
1198 >            shouldThrow();
1199 >        } catch (NullPointerException success) {}
1200 >    }
1201 >
1202 >    /**
1203 >     * hasQueuedThread reports whether a thread is queued.
1204 >     */
1205 >    public void testHasQueuedThread() throws InterruptedException {
1206 >        final PublicReentrantReadWriteLock lock = new PublicReentrantReadWriteLock();
1207 >        Thread t1 = new Thread(new InterruptedLockRunnable(lock));
1208 >        Thread t2 = new Thread(new InterruptibleLockRunnable(lock));
1209 >        assertFalse(lock.hasQueuedThread(t1));
1210 >        assertFalse(lock.hasQueuedThread(t2));
1211 >        lock.writeLock().lock();
1212 >        long startTime = System.nanoTime();
1213 >        t1.start();
1214 >        waitForQueuedThread(lock, t1);
1215 >        assertTrue(lock.hasQueuedThread(t1));
1216 >        assertFalse(lock.hasQueuedThread(t2));
1217 >        t2.start();
1218 >        waitForQueuedThread(lock, t2);
1219 >        assertTrue(lock.hasQueuedThread(t1));
1220 >        assertTrue(lock.hasQueuedThread(t2));
1221 >        t1.interrupt();
1222 >        awaitTermination(t1);
1223 >        assertFalse(lock.hasQueuedThread(t1));
1224 >        assertTrue(lock.hasQueuedThread(t2));
1225 >        lock.writeLock().unlock();
1226 >        awaitTermination(t2);
1227 >        assertFalse(lock.hasQueuedThread(t1));
1228 >        assertFalse(lock.hasQueuedThread(t2));
1229 >    }
1230 >
1231 >    /**
1232 >     * getQueueLength reports number of waiting threads
1233 >     */
1234 >    public void testGetQueueLength() throws InterruptedException {
1235 >        final PublicReentrantReadWriteLock lock = new PublicReentrantReadWriteLock();
1236 >        Thread t1 = new Thread(new InterruptedLockRunnable(lock));
1237 >        Thread t2 = new Thread(new InterruptibleLockRunnable(lock));
1238 >        assertEquals(0, lock.getQueueLength());
1239 >        lock.writeLock().lock();
1240 >        long startTime = System.nanoTime();
1241 >        t1.start();
1242 >        waitForQueuedThread(lock, t1);
1243 >        assertEquals(1, lock.getQueueLength());
1244 >        t2.start();
1245 >        waitForQueuedThread(lock, t2);
1246 >        assertEquals(2, lock.getQueueLength());
1247 >        t1.interrupt();
1248 >        awaitTermination(t1);
1249 >        assertEquals(1, lock.getQueueLength());
1250 >        lock.writeLock().unlock();
1251 >        awaitTermination(t2);
1252 >        assertEquals(0, lock.getQueueLength());
1253      }
1254  
1255 +    /**
1256 +     * getQueuedThreads includes waiting threads
1257 +     */
1258 +    public void testGetQueuedThreads() throws InterruptedException {
1259 +        final PublicReentrantReadWriteLock lock = new PublicReentrantReadWriteLock();
1260 +        Thread t1 = new Thread(new InterruptedLockRunnable(lock));
1261 +        Thread t2 = new Thread(new InterruptibleLockRunnable(lock));
1262 +        assertTrue(lock.getQueuedThreads().isEmpty());
1263 +        lock.writeLock().lock();
1264 +        long startTime = System.nanoTime();
1265 +        assertTrue(lock.getQueuedThreads().isEmpty());
1266 +        t1.start();
1267 +        waitForQueuedThread(lock, t1);
1268 +        assertEquals(1, lock.getQueuedThreads().size());
1269 +        assertTrue(lock.getQueuedThreads().contains(t1));
1270 +        t2.start();
1271 +        waitForQueuedThread(lock, t2);
1272 +        assertEquals(2, lock.getQueuedThreads().size());
1273 +        assertTrue(lock.getQueuedThreads().contains(t1));
1274 +        assertTrue(lock.getQueuedThreads().contains(t2));
1275 +        t1.interrupt();
1276 +        awaitTermination(t1);
1277 +        assertFalse(lock.getQueuedThreads().contains(t1));
1278 +        assertTrue(lock.getQueuedThreads().contains(t2));
1279 +        assertEquals(1, lock.getQueuedThreads().size());
1280 +        lock.writeLock().unlock();
1281 +        awaitTermination(t2);
1282 +        assertTrue(lock.getQueuedThreads().isEmpty());
1283 +    }
1284 +
1285 +    /**
1286 +     * hasWaiters throws NPE if null
1287 +     */
1288 +    public void testHasWaitersNPE() {
1289 +        final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
1290 +        try {
1291 +            lock.hasWaiters(null);
1292 +            shouldThrow();
1293 +        } catch (NullPointerException success) {}
1294 +    }
1295 +
1296 +    /**
1297 +     * getWaitQueueLength throws NPE if null
1298 +     */
1299 +    public void testGetWaitQueueLengthNPE() {
1300 +        final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
1301 +        try {
1302 +            lock.getWaitQueueLength(null);
1303 +            shouldThrow();
1304 +        } catch (NullPointerException success) {}
1305 +    }
1306 +
1307 +    /**
1308 +     * getWaitingThreads throws NPE if null
1309 +     */
1310 +    public void testGetWaitingThreadsNPE() {
1311 +        final PublicReentrantReadWriteLock lock = new PublicReentrantReadWriteLock();
1312 +        try {
1313 +            lock.getWaitingThreads(null);
1314 +            shouldThrow();
1315 +        } catch (NullPointerException success) {}
1316 +    }
1317 +
1318 +    /**
1319 +     * hasWaiters throws IAE if not owned
1320 +     */
1321 +    public void testHasWaitersIAE() {
1322 +        final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
1323 +        final Condition c = lock.writeLock().newCondition();
1324 +        final ReentrantReadWriteLock lock2 = new ReentrantReadWriteLock();
1325 +        try {
1326 +            lock2.hasWaiters(c);
1327 +            shouldThrow();
1328 +        } catch (IllegalArgumentException success) {}
1329 +    }
1330 +
1331 +    /**
1332 +     * hasWaiters throws IMSE if not locked
1333 +     */
1334 +    public void testHasWaitersIMSE() {
1335 +        final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
1336 +        final Condition c = lock.writeLock().newCondition();
1337 +        try {
1338 +            lock.hasWaiters(c);
1339 +            shouldThrow();
1340 +        } catch (IllegalMonitorStateException success) {}
1341 +    }
1342 +
1343 +    /**
1344 +     * getWaitQueueLength throws IAE if not owned
1345 +     */
1346 +    public void testGetWaitQueueLengthIAE() {
1347 +        final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
1348 +        final Condition c = lock.writeLock().newCondition();
1349 +        final ReentrantReadWriteLock lock2 = new ReentrantReadWriteLock();
1350 +        try {
1351 +            lock2.getWaitQueueLength(c);
1352 +            shouldThrow();
1353 +        } catch (IllegalArgumentException success) {}
1354 +    }
1355 +
1356 +    /**
1357 +     * getWaitQueueLength throws IMSE if not locked
1358 +     */
1359 +    public void testGetWaitQueueLengthIMSE() {
1360 +        final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
1361 +        final Condition c = lock.writeLock().newCondition();
1362 +        try {
1363 +            lock.getWaitQueueLength(c);
1364 +            shouldThrow();
1365 +        } catch (IllegalMonitorStateException success) {}
1366 +    }
1367 +
1368 +    /**
1369 +     * getWaitingThreads throws IAE if not owned
1370 +     */
1371 +    public void testGetWaitingThreadsIAE() {
1372 +        final PublicReentrantReadWriteLock lock = new PublicReentrantReadWriteLock();
1373 +        final Condition c = lock.writeLock().newCondition();
1374 +        final PublicReentrantReadWriteLock lock2 = new PublicReentrantReadWriteLock();
1375 +        try {
1376 +            lock2.getWaitingThreads(c);
1377 +            shouldThrow();
1378 +        } catch (IllegalArgumentException success) {}
1379 +    }
1380 +
1381 +    /**
1382 +     * getWaitingThreads throws IMSE if not locked
1383 +     */
1384 +    public void testGetWaitingThreadsIMSE() {
1385 +        final PublicReentrantReadWriteLock lock = new PublicReentrantReadWriteLock();
1386 +        final Condition c = lock.writeLock().newCondition();
1387 +        try {
1388 +            lock.getWaitingThreads(c);
1389 +            shouldThrow();
1390 +        } catch (IllegalMonitorStateException success) {}
1391 +    }
1392 +
1393 +    /**
1394 +     * hasWaiters returns true when a thread is waiting, else false
1395 +     */
1396 +    public void testHasWaiters() throws InterruptedException {
1397 +        final PublicReentrantReadWriteLock lock = new PublicReentrantReadWriteLock();
1398 +        final Condition c = lock.writeLock().newCondition();
1399 +        final CountDownLatch locked = new CountDownLatch(1);
1400 +        Thread t = newStartedThread(new CheckedRunnable() {
1401 +            public void realRun() throws InterruptedException {
1402 +                lock.writeLock().lock();
1403 +                assertFalse(lock.hasWaiters(c));
1404 +                locked.countDown();
1405 +                assertEquals(0, lock.getWaitQueueLength(c));
1406 +                c.await();
1407 +                lock.writeLock().unlock();
1408 +            }});
1409 +
1410 +        locked.await();
1411 +        lock.writeLock().lock();
1412 +        assertTrue(lock.hasWaiters(c));
1413 +        assertEquals(1, lock.getWaitQueueLength(c));
1414 +        c.signal();
1415 +        assertHasNoWaiters(lock, c);
1416 +        lock.writeLock().unlock();
1417 +        awaitTermination(t);
1418 +        assertHasNoWaiters(lock, c);
1419 +    }
1420 +
1421 +    /**
1422 +     * getWaitQueueLength returns number of waiting threads
1423 +     */
1424 +    public void testGetWaitQueueLength() throws InterruptedException {
1425 +        final PublicReentrantReadWriteLock lock = new PublicReentrantReadWriteLock();
1426 +        final Condition c = lock.writeLock().newCondition();
1427 +        final CountDownLatch locked = new CountDownLatch(1);
1428 +        Thread t = newStartedThread(new CheckedRunnable() {
1429 +            public void realRun() throws InterruptedException {
1430 +                lock.writeLock().lock();
1431 +                assertEquals(0, lock.getWaitQueueLength(c));
1432 +                locked.countDown();
1433 +                c.await();
1434 +                lock.writeLock().unlock();
1435 +            }});
1436 +
1437 +        locked.await();
1438 +        lock.writeLock().lock();
1439 +        assertHasWaiters(lock, c, t);
1440 +        assertEquals(1, lock.getWaitQueueLength(c));
1441 +        c.signal();
1442 +        assertHasNoWaiters(lock, c);
1443 +        assertEquals(0, lock.getWaitQueueLength(c));
1444 +        lock.writeLock().unlock();
1445 +        awaitTermination(t);
1446 +    }
1447 +
1448 +    /**
1449 +     * getWaitingThreads returns only and all waiting threads
1450 +     */
1451 +    public void testGetWaitingThreads() throws InterruptedException {
1452 +        final PublicReentrantReadWriteLock lock = new PublicReentrantReadWriteLock();
1453 +        final Condition c = lock.writeLock().newCondition();
1454 +        final CountDownLatch locked1 = new CountDownLatch(1);
1455 +        final CountDownLatch locked2 = new CountDownLatch(1);
1456 +        Thread t1 = new Thread(new CheckedRunnable() {
1457 +            public void realRun() throws InterruptedException {
1458 +                lock.writeLock().lock();
1459 +                assertTrue(lock.getWaitingThreads(c).isEmpty());
1460 +                locked1.countDown();
1461 +                c.await();
1462 +                lock.writeLock().unlock();
1463 +            }});
1464 +
1465 +        Thread t2 = new Thread(new CheckedRunnable() {
1466 +            public void realRun() throws InterruptedException {
1467 +                lock.writeLock().lock();
1468 +                assertFalse(lock.getWaitingThreads(c).isEmpty());
1469 +                locked2.countDown();
1470 +                c.await();
1471 +                lock.writeLock().unlock();
1472 +            }});
1473 +
1474 +        lock.writeLock().lock();
1475 +        assertTrue(lock.getWaitingThreads(c).isEmpty());
1476 +        lock.writeLock().unlock();
1477 +
1478 +        t1.start();
1479 +        locked1.await();
1480 +        t2.start();
1481 +        locked2.await();
1482 +
1483 +        lock.writeLock().lock();
1484 +        assertTrue(lock.hasWaiters(c));
1485 +        assertTrue(lock.getWaitingThreads(c).contains(t1));
1486 +        assertTrue(lock.getWaitingThreads(c).contains(t2));
1487 +        assertEquals(2, lock.getWaitingThreads(c).size());
1488 +        c.signalAll();
1489 +        assertHasNoWaiters(lock, c);
1490 +        lock.writeLock().unlock();
1491 +
1492 +        awaitTermination(t1);
1493 +        awaitTermination(t2);
1494 +
1495 +        assertHasNoWaiters(lock, c);
1496 +    }
1497 +
1498 +    /**
1499 +     * toString indicates current lock state
1500 +     */
1501 +    public void testToString() {
1502 +        ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
1503 +        String us = lock.toString();
1504 +        assertTrue(us.indexOf("Write locks = 0") >= 0);
1505 +        assertTrue(us.indexOf("Read locks = 0") >= 0);
1506 +        lock.writeLock().lock();
1507 +        String ws = lock.toString();
1508 +        assertTrue(ws.indexOf("Write locks = 1") >= 0);
1509 +        assertTrue(ws.indexOf("Read locks = 0") >= 0);
1510 +        lock.writeLock().unlock();
1511 +        lock.readLock().lock();
1512 +        lock.readLock().lock();
1513 +        String rs = lock.toString();
1514 +        assertTrue(rs.indexOf("Write locks = 0") >= 0);
1515 +        assertTrue(rs.indexOf("Read locks = 2") >= 0);
1516 +    }
1517 +
1518 +    /**
1519 +     * readLock.toString indicates current lock state
1520 +     */
1521 +    public void testReadLockToString() {
1522 +        ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
1523 +        String us = lock.readLock().toString();
1524 +        assertTrue(us.indexOf("Read locks = 0") >= 0);
1525 +        lock.readLock().lock();
1526 +        lock.readLock().lock();
1527 +        String rs = lock.readLock().toString();
1528 +        assertTrue(rs.indexOf("Read locks = 2") >= 0);
1529 +    }
1530 +
1531 +    /**
1532 +     * writeLock.toString indicates current lock state
1533 +     */
1534 +    public void testWriteLockToString() {
1535 +        ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
1536 +        String us = lock.writeLock().toString();
1537 +        assertTrue(us.indexOf("Unlocked") >= 0);
1538 +        lock.writeLock().lock();
1539 +        String ls = lock.writeLock().toString();
1540 +        assertTrue(ls.indexOf("Locked") >= 0);
1541 +    }
1542  
1543   }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines