/** awaitUninterruptibly is uninterruptible */
  public void testAwaitUninterruptibly() {
    final Mutex sync = new Mutex();
    final ConditionObject c = sync.newCondition();
    final BooleanLatch pleaseInterrupt = new BooleanLatch();
    Thread t =
        newStartedThread(
            new CheckedRunnable() {
              public void realRun() {
                sync.acquire();
                assertTrue(pleaseInterrupt.releaseShared(0));
                c.awaitUninterruptibly();
                assertTrue(Thread.interrupted());
                assertHasWaitersLocked(sync, c, NO_THREADS);
                sync.release();
              }
            });

    pleaseInterrupt.acquireShared(0);
    sync.acquire();
    assertHasWaitersLocked(sync, c, t);
    sync.release();
    t.interrupt();
    assertHasWaitersUnlocked(sync, c, t);
    assertThreadStaysAlive(t);
    sync.acquire();
    assertHasWaitersLocked(sync, c, t);
    assertHasExclusiveQueuedThreads(sync, NO_THREADS);
    c.signal();
    assertHasWaitersLocked(sync, c, NO_THREADS);
    assertHasExclusiveQueuedThreads(sync, t);
    sync.release();
    awaitTermination(t);
  }
  /** hasWaiters returns true when a thread is waiting, else false */
  public void testHasWaiters() {
    final Mutex sync = new Mutex();
    final ConditionObject c = sync.newCondition();
    final BooleanLatch acquired = new BooleanLatch();
    Thread t =
        newStartedThread(
            new CheckedRunnable() {
              public void realRun() throws InterruptedException {
                sync.acquire();
                assertHasWaitersLocked(sync, c, NO_THREADS);
                assertFalse(sync.hasWaiters(c));
                assertTrue(acquired.releaseShared(0));
                c.await();
                sync.release();
              }
            });

    acquired.acquireShared(0);
    sync.acquire();
    assertHasWaitersLocked(sync, c, t);
    assertHasExclusiveQueuedThreads(sync, NO_THREADS);
    assertTrue(sync.hasWaiters(c));
    c.signal();
    assertHasWaitersLocked(sync, c, NO_THREADS);
    assertHasExclusiveQueuedThreads(sync, t);
    assertFalse(sync.hasWaiters(c));
    sync.release();

    awaitTermination(t);
    assertHasWaitersUnlocked(sync, c, NO_THREADS);
  }
 /** Calling signalAll without holding sync throws IllegalMonitorStateException */
 public void testSignalAll_IMSE() {
   final Mutex sync = new Mutex();
   final ConditionObject c = sync.newCondition();
   try {
     c.signalAll();
     shouldThrow();
   } catch (IllegalMonitorStateException success) {
   }
 }
 /** Calling signal without holding sync throws IllegalMonitorStateException */
 public void testSignal_IMSE() {
   final Mutex sync = new Mutex();
   final ConditionObject c = sync.newCondition();
   try {
     c.signal();
     shouldThrow();
   } catch (IllegalMonitorStateException success) {
   }
   assertHasWaitersUnlocked(sync, c, NO_THREADS);
 }
  /** getWaitQueueLength returns number of waiting threads */
  public void testGetWaitQueueLength() {
    final Mutex sync = new Mutex();
    final ConditionObject c = sync.newCondition();
    final BooleanLatch acquired1 = new BooleanLatch();
    final BooleanLatch acquired2 = new BooleanLatch();
    final Thread t1 =
        newStartedThread(
            new CheckedRunnable() {
              public void realRun() throws InterruptedException {
                sync.acquire();
                assertHasWaitersLocked(sync, c, NO_THREADS);
                assertEquals(0, sync.getWaitQueueLength(c));
                assertTrue(acquired1.releaseShared(0));
                c.await();
                sync.release();
              }
            });
    acquired1.acquireShared(0);
    sync.acquire();
    assertHasWaitersLocked(sync, c, t1);
    assertEquals(1, sync.getWaitQueueLength(c));
    sync.release();

    final Thread t2 =
        newStartedThread(
            new CheckedRunnable() {
              public void realRun() throws InterruptedException {
                sync.acquire();
                assertHasWaitersLocked(sync, c, t1);
                assertEquals(1, sync.getWaitQueueLength(c));
                assertTrue(acquired2.releaseShared(0));
                c.await();
                sync.release();
              }
            });
    acquired2.acquireShared(0);
    sync.acquire();
    assertHasWaitersLocked(sync, c, t1, t2);
    assertHasExclusiveQueuedThreads(sync, NO_THREADS);
    assertEquals(2, sync.getWaitQueueLength(c));
    c.signalAll();
    assertHasWaitersLocked(sync, c, NO_THREADS);
    assertHasExclusiveQueuedThreads(sync, t1, t2);
    assertEquals(0, sync.getWaitQueueLength(c));
    sync.release();

    awaitTermination(t1);
    awaitTermination(t2);
    assertHasWaitersUnlocked(sync, c, NO_THREADS);
  }
 /** Awaits condition using the specified AwaitMethod. */
 void await(ConditionObject c, AwaitMethod awaitMethod) throws InterruptedException {
   long timeoutMillis = 2 * LONG_DELAY_MS;
   switch (awaitMethod) {
     case await:
       c.await();
       break;
     case awaitTimed:
       assertTrue(c.await(timeoutMillis, MILLISECONDS));
       break;
     case awaitNanos:
       long nanosTimeout = MILLISECONDS.toNanos(timeoutMillis);
       long nanosRemaining = c.awaitNanos(nanosTimeout);
       assertTrue(nanosRemaining > 0);
       break;
     case awaitUntil:
       assertTrue(c.awaitUntil(delayedDate(timeoutMillis)));
       break;
   }
 }
  public void testSignalAll(final AwaitMethod awaitMethod) {
    final Mutex sync = new Mutex();
    final ConditionObject c = sync.newCondition();
    final BooleanLatch acquired1 = new BooleanLatch();
    final BooleanLatch acquired2 = new BooleanLatch();
    Thread t1 =
        newStartedThread(
            new CheckedRunnable() {
              public void realRun() throws InterruptedException {
                sync.acquire();
                acquired1.releaseShared(0);
                await(c, awaitMethod);
                sync.release();
              }
            });

    Thread t2 =
        newStartedThread(
            new CheckedRunnable() {
              public void realRun() throws InterruptedException {
                sync.acquire();
                acquired2.releaseShared(0);
                await(c, awaitMethod);
                sync.release();
              }
            });

    acquired1.acquireShared(0);
    acquired2.acquireShared(0);
    sync.acquire();
    assertHasWaitersLocked(sync, c, t1, t2);
    assertHasExclusiveQueuedThreads(sync, NO_THREADS);
    c.signalAll();
    assertHasWaitersLocked(sync, c, NO_THREADS);
    assertHasExclusiveQueuedThreads(sync, t1, t2);
    sync.release();
    awaitTermination(t1);
    awaitTermination(t2);
  }
 /** Checks that awaiting the given condition times out (using the default timeout duration). */
 void assertAwaitTimesOut(ConditionObject c, AwaitMethod awaitMethod) {
   long timeoutMillis = timeoutMillis();
   long startTime = System.nanoTime();
   try {
     switch (awaitMethod) {
       case awaitTimed:
         assertFalse(c.await(timeoutMillis, MILLISECONDS));
         break;
       case awaitNanos:
         long nanosTimeout = MILLISECONDS.toNanos(timeoutMillis);
         long nanosRemaining = c.awaitNanos(nanosTimeout);
         assertTrue(nanosRemaining <= 0);
         break;
       case awaitUntil:
         assertFalse(c.awaitUntil(delayedDate(timeoutMillis)));
         break;
       default:
         throw new UnsupportedOperationException();
     }
   } catch (InterruptedException ie) {
     threadUnexpectedException(ie);
   }
   assertTrue(millisElapsedSince(startTime) >= timeoutMillis);
 }