--- jsr166/src/test/tck/ReentrantReadWriteLockTest.java 2004/01/25 13:25:28 1.19 +++ jsr166/src/test/tck/ReentrantReadWriteLockTest.java 2009/11/16 05:30:08 1.30 @@ -2,8 +2,8 @@ * Written by Doug Lea with assistance from members of JCP JSR-166 * Expert Group and released to the public domain, as explained at * http://creativecommons.org/licenses/publicdomain - * Other contributors include Andrew Wright, Jeffrey Hayes, - * Pat Fisher, Mike Judd. + * Other contributors include Andrew Wright, Jeffrey Hayes, + * Pat Fisher, Mike Judd. */ import junit.framework.*; @@ -14,7 +14,7 @@ import java.util.*; public class ReentrantReadWriteLockTest extends JSR166TestCase { public static void main(String[] args) { - junit.textui.TestRunner.run (suite()); + junit.textui.TestRunner.run (suite()); } public static Test suite() { return new TestSuite(ReentrantReadWriteLockTest.class); @@ -29,7 +29,7 @@ public class ReentrantReadWriteLockTest public void run() { try { lock.writeLock().lockInterruptibly(); - } catch(InterruptedException success){} + } catch (InterruptedException success) {} } } @@ -45,7 +45,7 @@ public class ReentrantReadWriteLockTest try { lock.writeLock().lockInterruptibly(); threadShouldThrow(); - } catch(InterruptedException success){} + } catch (InterruptedException success) {} } } @@ -54,18 +54,18 @@ public class ReentrantReadWriteLockTest */ static class PublicReentrantReadWriteLock extends ReentrantReadWriteLock { PublicReentrantReadWriteLock() { super(); } - public Collection getQueuedThreads() { - return super.getQueuedThreads(); + public Collection getQueuedThreads() { + return super.getQueuedThreads(); } - public Collection getWaitingThreads(Condition c) { - return super.getWaitingThreads(c); + public Collection getWaitingThreads(Condition c) { + return super.getWaitingThreads(c); } } /** * Constructor sets given fairness, and is in unlocked state */ - public void testConstructor() { + public void testConstructor() { ReentrantReadWriteLock rl = new ReentrantReadWriteLock(); assertFalse(rl.isFair()); assertFalse(rl.isWriteLocked()); @@ -79,15 +79,17 @@ public class ReentrantReadWriteLockTest /** * write-locking and read-locking an unlocked lock succeed */ - public void testLock() { + public void testLock() { ReentrantReadWriteLock rl = new ReentrantReadWriteLock(); rl.writeLock().lock(); assertTrue(rl.isWriteLocked()); assertTrue(rl.isWriteLockedByCurrentThread()); + assertTrue(rl.writeLock().isHeldByCurrentThread()); assertEquals(0, rl.getReadLockCount()); rl.writeLock().unlock(); assertFalse(rl.isWriteLocked()); assertFalse(rl.isWriteLockedByCurrentThread()); + assertFalse(rl.writeLock().isHeldByCurrentThread()); assertEquals(0, rl.getReadLockCount()); rl.readLock().lock(); assertFalse(rl.isWriteLocked()); @@ -103,15 +105,17 @@ public class ReentrantReadWriteLockTest /** * locking an unlocked fair lock succeeds */ - public void testFairLock() { + public void testFairLock() { ReentrantReadWriteLock rl = new ReentrantReadWriteLock(true); rl.writeLock().lock(); assertTrue(rl.isWriteLocked()); assertTrue(rl.isWriteLockedByCurrentThread()); + assertTrue(rl.writeLock().isHeldByCurrentThread()); assertEquals(0, rl.getReadLockCount()); rl.writeLock().unlock(); assertFalse(rl.isWriteLocked()); assertFalse(rl.isWriteLockedByCurrentThread()); + assertFalse(rl.writeLock().isHeldByCurrentThread()); assertEquals(0, rl.getReadLockCount()); rl.readLock().lock(); assertFalse(rl.isWriteLocked()); @@ -126,35 +130,65 @@ public class ReentrantReadWriteLockTest /** * getWriteHoldCount returns number of recursive holds */ - public void testGetHoldCount() { + public void testGetWriteHoldCount() { ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); - for(int i = 1; i <= SIZE; i++) { + for (int i = 1; i <= SIZE; i++) { lock.writeLock().lock(); assertEquals(i,lock.getWriteHoldCount()); } - for(int i = SIZE; i > 0; i--) { + for (int i = SIZE; i > 0; i--) { lock.writeLock().unlock(); assertEquals(i-1,lock.getWriteHoldCount()); } } - + + /** + * WriteLock.getHoldCount returns number of recursive holds + */ + public void testGetHoldCount() { + ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); + for (int i = 1; i <= SIZE; i++) { + lock.writeLock().lock(); + assertEquals(i,lock.writeLock().getHoldCount()); + } + for (int i = SIZE; i > 0; i--) { + lock.writeLock().unlock(); + assertEquals(i-1,lock.writeLock().getHoldCount()); + } + } + + /** + * getReadHoldCount returns number of recursive holds + */ + public void testGetReadHoldCount() { + ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); + for (int i = 1; i <= SIZE; i++) { + lock.readLock().lock(); + assertEquals(i,lock.getReadHoldCount()); + } + for (int i = SIZE; i > 0; i--) { + lock.readLock().unlock(); + assertEquals(i-1,lock.getReadHoldCount()); + } + } + /** * write-unlocking an unlocked lock throws IllegalMonitorStateException */ - public void testUnlock_IllegalMonitorStateException() { + public void testUnlock_IllegalMonitorStateException() { ReentrantReadWriteLock rl = new ReentrantReadWriteLock(); try { rl.writeLock().unlock(); shouldThrow(); - } catch(IllegalMonitorStateException success){} + } catch (IllegalMonitorStateException success) {} } /** * write-lockInterruptibly is interruptible */ - public void testWriteLockInterruptibly_Interrupted() { + public void testWriteLockInterruptibly_Interrupted() { final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); Thread t = new Thread(new Runnable() { public void run() { @@ -163,31 +197,33 @@ public class ReentrantReadWriteLockTest lock.writeLock().unlock(); lock.writeLock().lockInterruptibly(); lock.writeLock().unlock(); - } catch(InterruptedException success){} + } catch (InterruptedException success) {} } }); try { lock.writeLock().lock(); t.start(); + Thread.sleep(SHORT_DELAY_MS); t.interrupt(); + Thread.sleep(SHORT_DELAY_MS); lock.writeLock().unlock(); t.join(); - } catch(Exception e){ + } catch (Exception e) { unexpectedException(); } - } + } /** * timed write-tryLock is interruptible */ - public void testWriteTryLock_Interrupted() { + public void testWriteTryLock_Interrupted() { final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); lock.writeLock().lock(); Thread t = new Thread(new Runnable() { public void run() { try { lock.writeLock().tryLock(1000,TimeUnit.MILLISECONDS); - } catch(InterruptedException success){} + } catch (InterruptedException success) {} } }); try { @@ -195,7 +231,7 @@ public class ReentrantReadWriteLockTest t.interrupt(); lock.writeLock().unlock(); t.join(); - } catch(Exception e){ + } catch (Exception e) { unexpectedException(); } } @@ -203,30 +239,32 @@ public class ReentrantReadWriteLockTest /** * read-lockInterruptibly is interruptible */ - public void testReadLockInterruptibly_Interrupted() { + public void testReadLockInterruptibly_Interrupted() { final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); lock.writeLock().lock(); Thread t = new Thread(new Runnable() { public void run() { try { lock.readLock().lockInterruptibly(); - } catch(InterruptedException success){} + } catch (InterruptedException success) {} } }); try { t.start(); + Thread.sleep(SHORT_DELAY_MS); t.interrupt(); + Thread.sleep(SHORT_DELAY_MS); lock.writeLock().unlock(); t.join(); - } catch(Exception e){ + } catch (Exception e) { unexpectedException(); } - } + } /** * timed read-tryLock is interruptible */ - public void testReadTryLock_Interrupted() { + public void testReadTryLock_Interrupted() { final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); lock.writeLock().lock(); Thread t = new Thread(new Runnable() { @@ -234,23 +272,23 @@ public class ReentrantReadWriteLockTest try { lock.readLock().tryLock(1000,TimeUnit.MILLISECONDS); threadShouldThrow(); - } catch(InterruptedException success){} + } catch (InterruptedException success) {} } }); try { t.start(); t.interrupt(); t.join(); - } catch(Exception e){ + } catch (Exception e) { unexpectedException(); } } - + /** * write-tryLock fails if locked */ - public void testWriteTryLockWhenLocked() { + public void testWriteTryLockWhenLocked() { final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); lock.writeLock().lock(); Thread t = new Thread(new Runnable() { @@ -262,15 +300,15 @@ public class ReentrantReadWriteLockTest t.start(); t.join(); lock.writeLock().unlock(); - } catch(Exception e){ + } catch (Exception e) { unexpectedException(); } - } + } /** * read-tryLock fails if locked */ - public void testReadTryLockWhenLocked() { + public void testReadTryLockWhenLocked() { final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); lock.writeLock().lock(); Thread t = new Thread(new Runnable() { @@ -282,15 +320,15 @@ public class ReentrantReadWriteLockTest t.start(); t.join(); lock.writeLock().unlock(); - } catch(Exception e){ + } catch (Exception e) { unexpectedException(); } - } + } /** * Multiple threads can hold a read lock when not write-locked */ - public void testMultipleReadLocks() { + public void testMultipleReadLocks() { final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); lock.readLock().lock(); Thread t = new Thread(new Runnable() { @@ -303,15 +341,15 @@ public class ReentrantReadWriteLockTest t.start(); t.join(); lock.readLock().unlock(); - } catch(Exception e){ + } catch (Exception e) { unexpectedException(); } - } + } /** * A writelock succeeds after reading threads unlock */ - public void testWriteAfterMultipleReadLocks() { + public void testWriteAfterMultipleReadLocks() { final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); lock.readLock().lock(); Thread t1 = new Thread(new Runnable() { @@ -336,16 +374,62 @@ public class ReentrantReadWriteLockTest t2.join(MEDIUM_DELAY_MS); assertTrue(!t1.isAlive()); assertTrue(!t2.isAlive()); - - } catch(Exception e){ + + } catch (Exception e) { unexpectedException(); } - } + } /** * Readlocks succeed after a writing thread unlocks */ - public void testReadAfterWriteLock() { + public void testReadAfterWriteLock() { + final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); + lock.writeLock().lock(); + Thread t1 = new Thread(new Runnable() { + public void run() { + lock.readLock().lock(); + lock.readLock().unlock(); + } + }); + Thread t2 = new Thread(new Runnable() { + public void run() { + lock.readLock().lock(); + lock.readLock().unlock(); + } + }); + + try { + t1.start(); + t2.start(); + Thread.sleep(SHORT_DELAY_MS); + lock.writeLock().unlock(); + t1.join(MEDIUM_DELAY_MS); + t2.join(MEDIUM_DELAY_MS); + assertTrue(!t1.isAlive()); + assertTrue(!t2.isAlive()); + + } catch (Exception e) { + unexpectedException(); + } + } + + /** + * Read trylock succeeds if write locked by current thread + */ + public void testReadHoldingWriteLock() { + final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); + lock.writeLock().lock(); + assertTrue(lock.readLock().tryLock()); + lock.readLock().unlock(); + lock.writeLock().unlock(); + } + + /** + * Read lock succeeds if write locked by current thread even if + * other threads are waiting for readlock + */ + public void testReadHoldingWriteLock2() { final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); lock.writeLock().lock(); Thread t1 = new Thread(new Runnable() { @@ -364,23 +448,240 @@ public class ReentrantReadWriteLockTest try { t1.start(); t2.start(); + lock.readLock().lock(); + lock.readLock().unlock(); + Thread.sleep(SHORT_DELAY_MS); + lock.readLock().lock(); + lock.readLock().unlock(); + lock.writeLock().unlock(); + t1.join(MEDIUM_DELAY_MS); + t2.join(MEDIUM_DELAY_MS); + assertTrue(!t1.isAlive()); + assertTrue(!t2.isAlive()); + + } catch (Exception e) { + unexpectedException(); + } + } + + /** + * Read lock succeeds if write locked by current thread even if + * other threads are waiting for writelock + */ + public void testReadHoldingWriteLock3() { + final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); + lock.writeLock().lock(); + Thread t1 = new Thread(new Runnable() { + public void run() { + lock.writeLock().lock(); + lock.writeLock().unlock(); + } + }); + Thread t2 = new Thread(new Runnable() { + public void run() { + lock.writeLock().lock(); + lock.writeLock().unlock(); + } + }); + + try { + t1.start(); + t2.start(); + lock.readLock().lock(); + lock.readLock().unlock(); + Thread.sleep(SHORT_DELAY_MS); + lock.readLock().lock(); + lock.readLock().unlock(); + lock.writeLock().unlock(); + t1.join(MEDIUM_DELAY_MS); + t2.join(MEDIUM_DELAY_MS); + assertTrue(!t1.isAlive()); + assertTrue(!t2.isAlive()); + + } catch (Exception e) { + unexpectedException(); + } + } + + + /** + * Write lock succeeds if write locked by current thread even if + * other threads are waiting for writelock + */ + public void testWriteHoldingWriteLock4() { + final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); + lock.writeLock().lock(); + Thread t1 = new Thread(new Runnable() { + public void run() { + lock.writeLock().lock(); + lock.writeLock().unlock(); + } + }); + Thread t2 = new Thread(new Runnable() { + public void run() { + lock.writeLock().lock(); + lock.writeLock().unlock(); + } + }); + + try { + t1.start(); + t2.start(); + lock.writeLock().lock(); + lock.writeLock().unlock(); Thread.sleep(SHORT_DELAY_MS); + lock.writeLock().lock(); + lock.writeLock().unlock(); lock.writeLock().unlock(); t1.join(MEDIUM_DELAY_MS); t2.join(MEDIUM_DELAY_MS); assertTrue(!t1.isAlive()); assertTrue(!t2.isAlive()); - - } catch(Exception e){ + + } catch (Exception e) { unexpectedException(); } - } + } + + + /** + * Fair Read trylock succeeds if write locked by current thread + */ + public void testReadHoldingWriteLockFair() { + final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(true); + lock.writeLock().lock(); + assertTrue(lock.readLock().tryLock()); + lock.readLock().unlock(); + lock.writeLock().unlock(); + } + + /** + * Fair Read lock succeeds if write locked by current thread even if + * other threads are waiting for readlock + */ + public void testReadHoldingWriteLockFair2() { + final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(true); + lock.writeLock().lock(); + Thread t1 = new Thread(new Runnable() { + public void run() { + lock.readLock().lock(); + lock.readLock().unlock(); + } + }); + Thread t2 = new Thread(new Runnable() { + public void run() { + lock.readLock().lock(); + lock.readLock().unlock(); + } + }); + + try { + t1.start(); + t2.start(); + lock.readLock().lock(); + lock.readLock().unlock(); + Thread.sleep(SHORT_DELAY_MS); + lock.readLock().lock(); + lock.readLock().unlock(); + lock.writeLock().unlock(); + t1.join(MEDIUM_DELAY_MS); + t2.join(MEDIUM_DELAY_MS); + assertTrue(!t1.isAlive()); + assertTrue(!t2.isAlive()); + + } catch (Exception e) { + unexpectedException(); + } + } + + + /** + * Fair Read lock succeeds if write locked by current thread even if + * other threads are waiting for writelock + */ + public void testReadHoldingWriteLockFair3() { + final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(true); + lock.writeLock().lock(); + Thread t1 = new Thread(new Runnable() { + public void run() { + lock.writeLock().lock(); + lock.writeLock().unlock(); + } + }); + Thread t2 = new Thread(new Runnable() { + public void run() { + lock.writeLock().lock(); + lock.writeLock().unlock(); + } + }); + + try { + t1.start(); + t2.start(); + lock.readLock().lock(); + lock.readLock().unlock(); + Thread.sleep(SHORT_DELAY_MS); + lock.readLock().lock(); + lock.readLock().unlock(); + lock.writeLock().unlock(); + t1.join(MEDIUM_DELAY_MS); + t2.join(MEDIUM_DELAY_MS); + assertTrue(!t1.isAlive()); + assertTrue(!t2.isAlive()); + + } catch (Exception e) { + unexpectedException(); + } + } + + + /** + * Fair Write lock succeeds if write locked by current thread even if + * other threads are waiting for writelock + */ + public void testWriteHoldingWriteLockFair4() { + final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(true); + lock.writeLock().lock(); + Thread t1 = new Thread(new Runnable() { + public void run() { + lock.writeLock().lock(); + lock.writeLock().unlock(); + } + }); + Thread t2 = new Thread(new Runnable() { + public void run() { + lock.writeLock().lock(); + lock.writeLock().unlock(); + } + }); + + try { + t1.start(); + t2.start(); + Thread.sleep(SHORT_DELAY_MS); + assertTrue(lock.isWriteLockedByCurrentThread()); + assertTrue(lock.getWriteHoldCount() == 1); + lock.writeLock().lock(); + assertTrue(lock.getWriteHoldCount() == 2); + lock.writeLock().unlock(); + lock.writeLock().lock(); + lock.writeLock().unlock(); + lock.writeLock().unlock(); + t1.join(MEDIUM_DELAY_MS); + t2.join(MEDIUM_DELAY_MS); + assertTrue(!t1.isAlive()); + assertTrue(!t2.isAlive()); + + } catch (Exception e) { + unexpectedException(); + } + } /** * Read tryLock succeeds if readlocked but not writelocked */ - public void testTryLockWhenReadLocked() { + public void testTryLockWhenReadLocked() { final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); lock.readLock().lock(); Thread t = new Thread(new Runnable() { @@ -393,17 +694,17 @@ public class ReentrantReadWriteLockTest t.start(); t.join(); lock.readLock().unlock(); - } catch(Exception e){ + } catch (Exception e) { unexpectedException(); } - } + } + - /** * write tryLock fails when readlocked */ - public void testWriteTryLockWhenReadLocked() { + public void testWriteTryLockWhenReadLocked() { final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); lock.readLock().lock(); Thread t = new Thread(new Runnable() { @@ -415,17 +716,61 @@ public class ReentrantReadWriteLockTest t.start(); t.join(); lock.readLock().unlock(); - } catch(Exception e){ + } catch (Exception e) { unexpectedException(); } - } + } + + + /** + * Fair Read tryLock succeeds if readlocked but not writelocked + */ + public void testTryLockWhenReadLockedFair() { + final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(true); + lock.readLock().lock(); + Thread t = new Thread(new Runnable() { + public void run() { + threadAssertTrue(lock.readLock().tryLock()); + lock.readLock().unlock(); + } + }); + try { + t.start(); + t.join(); + lock.readLock().unlock(); + } catch (Exception e) { + unexpectedException(); + } + } + + + + /** + * Fair write tryLock fails when readlocked + */ + public void testWriteTryLockWhenReadLockedFair() { + final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(true); + lock.readLock().lock(); + Thread t = new Thread(new Runnable() { + public void run() { + threadAssertFalse(lock.writeLock().tryLock()); + } + }); + try { + t.start(); + t.join(); + lock.readLock().unlock(); + } catch (Exception e) { + unexpectedException(); + } + } + - /** * write timed tryLock times out if locked */ - public void testWriteTryLock_Timeout() { + public void testWriteTryLock_Timeout() { final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); lock.writeLock().lock(); Thread t = new Thread(new Runnable() { @@ -441,15 +786,15 @@ public class ReentrantReadWriteLockTest t.start(); t.join(); lock.writeLock().unlock(); - } catch(Exception e){ + } catch (Exception e) { unexpectedException(); } - } + } /** * read timed tryLock times out if write-locked */ - public void testReadTryLock_Timeout() { + public void testReadTryLock_Timeout() { final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); lock.writeLock().lock(); Thread t = new Thread(new Runnable() { @@ -465,10 +810,10 @@ public class ReentrantReadWriteLockTest t.start(); t.join(); lock.writeLock().unlock(); - } catch(Exception e){ + } catch (Exception e) { unexpectedException(); } - } + } /** @@ -478,25 +823,27 @@ public class ReentrantReadWriteLockTest final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); try { lock.writeLock().lockInterruptibly(); - } catch(Exception e) { + } catch (Exception e) { unexpectedException(); } - Thread t = new Thread(new Runnable() { + Thread t = new Thread(new Runnable() { public void run() { try { lock.writeLock().lockInterruptibly(); threadShouldThrow(); } - catch(InterruptedException success) { + catch (InterruptedException success) { } } }); try { t.start(); + Thread.sleep(SHORT_DELAY_MS); t.interrupt(); + Thread.sleep(SHORT_DELAY_MS); t.join(); lock.writeLock().unlock(); - } catch(Exception e){ + } catch (Exception e) { unexpectedException(); } } @@ -508,25 +855,26 @@ public class ReentrantReadWriteLockTest final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); try { lock.writeLock().lockInterruptibly(); - } catch(Exception e) { + } catch (Exception e) { unexpectedException(); } - Thread t = new Thread(new Runnable() { + Thread t = new Thread(new Runnable() { public void run() { try { lock.readLock().lockInterruptibly(); threadShouldThrow(); } - catch(InterruptedException success) { + catch (InterruptedException success) { } } }); try { t.start(); + Thread.sleep(SHORT_DELAY_MS); t.interrupt(); t.join(); lock.writeLock().unlock(); - } catch(Exception e){ + } catch (Exception e) { unexpectedException(); } } @@ -535,7 +883,7 @@ public class ReentrantReadWriteLockTest * Calling await without holding lock throws IllegalMonitorStateException */ public void testAwait_IllegalMonitor() { - final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); + final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); final Condition c = lock.writeLock().newCondition(); try { c.await(); @@ -552,7 +900,7 @@ public class ReentrantReadWriteLockTest * Calling signal without holding lock throws IllegalMonitorStateException */ public void testSignal_IllegalMonitor() { - final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); + final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); final Condition c = lock.writeLock().newCondition(); try { c.signal(); @@ -569,7 +917,7 @@ public class ReentrantReadWriteLockTest * awaitNanos without a signal times out */ public void testAwaitNanos_Timeout() { - final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); + final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); final Condition c = lock.writeLock().newCondition(); try { lock.writeLock().lock(); @@ -587,11 +935,10 @@ public class ReentrantReadWriteLockTest * timed await without a signal times out */ public void testAwait_Timeout() { - final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); + final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); final Condition c = lock.writeLock().newCondition(); try { lock.writeLock().lock(); - assertFalse(c.await(10, TimeUnit.MILLISECONDS)); lock.writeLock().unlock(); } catch (Exception ex) { @@ -603,12 +950,11 @@ public class ReentrantReadWriteLockTest * awaitUntil without a signal times out */ public void testAwaitUntil_Timeout() { - final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); + final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); final Condition c = lock.writeLock().newCondition(); try { lock.writeLock().lock(); java.util.Date d = new java.util.Date(); - assertFalse(c.awaitUntil(new java.util.Date(d.getTime() + 10))); lock.writeLock().unlock(); } catch (Exception ex) { @@ -620,16 +966,16 @@ public class ReentrantReadWriteLockTest * await returns when signalled */ public void testAwait() { - final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); + final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); final Condition c = lock.writeLock().newCondition(); - Thread t = new Thread(new Runnable() { + Thread t = new Thread(new Runnable() { public void run() { try { lock.writeLock().lock(); c.await(); lock.writeLock().unlock(); } - catch(InterruptedException e) { + catch (InterruptedException e) { threadUnexpectedException(); } } @@ -649,32 +995,61 @@ public class ReentrantReadWriteLockTest } } + /** A helper class for uninterruptible wait tests */ + class UninterruptableThread extends Thread { + private Lock lock; + private Condition c; + + public volatile boolean canAwake = false; + public volatile boolean interrupted = false; + public volatile boolean lockStarted = false; + + public UninterruptableThread(Lock lock, Condition c) { + this.lock = lock; + this.c = c; + } + + public synchronized void run() { + lock.lock(); + lockStarted = true; + + while (!canAwake) { + c.awaitUninterruptibly(); + } + + interrupted = isInterrupted(); + lock.unlock(); + } + } + /** * awaitUninterruptibly doesn't abort on interrupt */ public void testAwaitUninterruptibly() { - final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); + final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); final Condition c = lock.writeLock().newCondition(); - Thread t = new Thread(new Runnable() { - public void run() { - lock.writeLock().lock(); - c.awaitUninterruptibly(); - lock.writeLock().unlock(); - } - }); + UninterruptableThread thread = new UninterruptableThread(lock.writeLock(), c); try { - t.start(); - Thread.sleep(SHORT_DELAY_MS); - t.interrupt(); + thread.start(); + + while (!thread.lockStarted) { + Thread.sleep(100); + } + lock.writeLock().lock(); - c.signal(); - lock.writeLock().unlock(); - assert(t.isInterrupted()); - t.join(SHORT_DELAY_MS); - assertFalse(t.isAlive()); - } - catch (Exception ex) { + try { + thread.interrupt(); + thread.canAwake = true; + c.signal(); + } finally { + lock.writeLock().unlock(); + } + + thread.join(); + assertTrue(thread.interrupted); + assertFalse(thread.isAlive()); + } catch (Exception ex) { unexpectedException(); } } @@ -683,9 +1058,9 @@ public class ReentrantReadWriteLockTest * await is interruptible */ public void testAwait_Interrupt() { - final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); + final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); final Condition c = lock.writeLock().newCondition(); - Thread t = new Thread(new Runnable() { + Thread t = new Thread(new Runnable() { public void run() { try { lock.writeLock().lock(); @@ -693,7 +1068,7 @@ public class ReentrantReadWriteLockTest lock.writeLock().unlock(); threadShouldThrow(); } - catch(InterruptedException success) { + catch (InterruptedException success) { } } }); @@ -714,9 +1089,9 @@ public class ReentrantReadWriteLockTest * awaitNanos is interruptible */ public void testAwaitNanos_Interrupt() { - final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); + final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); final Condition c = lock.writeLock().newCondition(); - Thread t = new Thread(new Runnable() { + Thread t = new Thread(new Runnable() { public void run() { try { lock.writeLock().lock(); @@ -724,7 +1099,7 @@ public class ReentrantReadWriteLockTest lock.writeLock().unlock(); threadShouldThrow(); } - catch(InterruptedException success) { + catch (InterruptedException success) { } } }); @@ -745,9 +1120,9 @@ public class ReentrantReadWriteLockTest * awaitUntil is interruptible */ public void testAwaitUntil_Interrupt() { - final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); + final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); final Condition c = lock.writeLock().newCondition(); - Thread t = new Thread(new Runnable() { + Thread t = new Thread(new Runnable() { public void run() { try { lock.writeLock().lock(); @@ -756,7 +1131,7 @@ public class ReentrantReadWriteLockTest lock.writeLock().unlock(); threadShouldThrow(); } - catch(InterruptedException success) { + catch (InterruptedException success) { } } }); @@ -777,29 +1152,29 @@ public class ReentrantReadWriteLockTest * signalAll wakes up all threads */ public void testSignalAll() { - final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); + final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); final Condition c = lock.writeLock().newCondition(); - Thread t1 = new Thread(new Runnable() { + Thread t1 = new Thread(new Runnable() { public void run() { try { lock.writeLock().lock(); c.await(); lock.writeLock().unlock(); } - catch(InterruptedException e) { + catch (InterruptedException e) { threadUnexpectedException(); } } }); - Thread t2 = new Thread(new Runnable() { + Thread t2 = new Thread(new Runnable() { public void run() { try { lock.writeLock().lock(); c.await(); lock.writeLock().unlock(); } - catch(InterruptedException e) { + catch (InterruptedException e) { threadUnexpectedException(); } } @@ -841,7 +1216,7 @@ public class ReentrantReadWriteLockTest ReentrantReadWriteLock r = (ReentrantReadWriteLock) in.readObject(); r.readLock().lock(); r.readLock().unlock(); - } catch(Exception e){ + } catch (Exception e) { e.printStackTrace(); unexpectedException(); } @@ -850,7 +1225,7 @@ public class ReentrantReadWriteLockTest /** * hasQueuedThreads reports whether there are waiting threads */ - public void testhasQueuedThreads() { + public void testhasQueuedThreads() { final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); Thread t1 = new Thread(new InterruptedLockRunnable(lock)); Thread t2 = new Thread(new InterruptibleLockRunnable(lock)); @@ -871,15 +1246,15 @@ public class ReentrantReadWriteLockTest assertFalse(lock.hasQueuedThreads()); t1.join(); t2.join(); - } catch(Exception e){ + } catch (Exception e) { unexpectedException(); } - } + } /** * hasQueuedThread(null) throws NPE */ - public void testHasQueuedThreadNPE() { + public void testHasQueuedThreadNPE() { final ReentrantReadWriteLock sync = new ReentrantReadWriteLock(); try { sync.hasQueuedThread(null); @@ -891,7 +1266,7 @@ public class ReentrantReadWriteLockTest /** * hasQueuedThread reports whether a thread is queued. */ - public void testHasQueuedThread() { + public void testHasQueuedThread() { final ReentrantReadWriteLock sync = new ReentrantReadWriteLock(); Thread t1 = new Thread(new InterruptedLockRunnable(sync)); Thread t2 = new Thread(new InterruptibleLockRunnable(sync)); @@ -917,16 +1292,16 @@ public class ReentrantReadWriteLockTest assertFalse(sync.hasQueuedThread(t2)); t1.join(); t2.join(); - } catch(Exception e){ + } catch (Exception e) { unexpectedException(); } - } + } /** * getQueueLength reports number of waiting threads */ - public void testGetQueueLength() { + public void testGetQueueLength() { final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); Thread t1 = new Thread(new InterruptedLockRunnable(lock)); Thread t2 = new Thread(new InterruptibleLockRunnable(lock)); @@ -947,15 +1322,15 @@ public class ReentrantReadWriteLockTest assertEquals(0, lock.getQueueLength()); t1.join(); t2.join(); - } catch(Exception e){ + } catch (Exception e) { unexpectedException(); } - } + } /** * getQueuedThreads includes waiting threads */ - public void testGetQueuedThreads() { + public void testGetQueuedThreads() { final PublicReentrantReadWriteLock lock = new PublicReentrantReadWriteLock(); Thread t1 = new Thread(new InterruptedLockRunnable(lock)); Thread t2 = new Thread(new InterruptibleLockRunnable(lock)); @@ -979,10 +1354,10 @@ public class ReentrantReadWriteLockTest assertTrue(lock.getQueuedThreads().isEmpty()); t1.join(); t2.join(); - } catch(Exception e){ + } catch (Exception e) { unexpectedException(); } - } + } /** * hasWaiters throws NPE if null @@ -1095,9 +1470,9 @@ public class ReentrantReadWriteLockTest * getWaitingThreads throws IAE if not owned */ public void testGetWaitingThreadsIAE() { - final PublicReentrantReadWriteLock lock = new PublicReentrantReadWriteLock(); + final PublicReentrantReadWriteLock lock = new PublicReentrantReadWriteLock(); final Condition c = (lock.writeLock().newCondition()); - final PublicReentrantReadWriteLock lock2 = new PublicReentrantReadWriteLock(); + final PublicReentrantReadWriteLock lock2 = new PublicReentrantReadWriteLock(); try { lock2.getWaitingThreads(c); shouldThrow(); @@ -1111,7 +1486,7 @@ public class ReentrantReadWriteLockTest * getWaitingThreads throws IMSE if not locked */ public void testGetWaitingThreadsIMSE() { - final PublicReentrantReadWriteLock lock = new PublicReentrantReadWriteLock(); + final PublicReentrantReadWriteLock lock = new PublicReentrantReadWriteLock(); final Condition c = (lock.writeLock().newCondition()); try { lock.getWaitingThreads(c); @@ -1129,7 +1504,7 @@ public class ReentrantReadWriteLockTest public void testHasWaiters() { final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); final Condition c = (lock.writeLock().newCondition()); - Thread t = new Thread(new Runnable() { + Thread t = new Thread(new Runnable() { public void run() { try { lock.writeLock().lock(); @@ -1138,7 +1513,7 @@ public class ReentrantReadWriteLockTest c.await(); lock.writeLock().unlock(); } - catch(InterruptedException e) { + catch (InterruptedException e) { threadUnexpectedException(); } } @@ -1171,7 +1546,7 @@ public class ReentrantReadWriteLockTest public void testGetWaitQueueLength() { final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); final Condition c = (lock.writeLock().newCondition()); - Thread t = new Thread(new Runnable() { + Thread t = new Thread(new Runnable() { public void run() { try { lock.writeLock().lock(); @@ -1180,7 +1555,7 @@ public class ReentrantReadWriteLockTest c.await(); lock.writeLock().unlock(); } - catch(InterruptedException e) { + catch (InterruptedException e) { threadUnexpectedException(); } } @@ -1212,9 +1587,9 @@ public class ReentrantReadWriteLockTest * getWaitingThreads returns only and all waiting threads */ public void testGetWaitingThreads() { - final PublicReentrantReadWriteLock lock = new PublicReentrantReadWriteLock(); + final PublicReentrantReadWriteLock lock = new PublicReentrantReadWriteLock(); final Condition c = lock.writeLock().newCondition(); - Thread t1 = new Thread(new Runnable() { + Thread t1 = new Thread(new Runnable() { public void run() { try { lock.writeLock().lock(); @@ -1222,13 +1597,13 @@ public class ReentrantReadWriteLockTest c.await(); lock.writeLock().unlock(); } - catch(InterruptedException e) { + catch (InterruptedException e) { threadUnexpectedException(); } } }); - Thread t2 = new Thread(new Runnable() { + Thread t2 = new Thread(new Runnable() { public void run() { try { lock.writeLock().lock(); @@ -1236,7 +1611,7 @@ public class ReentrantReadWriteLockTest c.await(); lock.writeLock().unlock(); } - catch(InterruptedException e) { + catch (InterruptedException e) { threadUnexpectedException(); } }