/** releaseShared has no effect when already signalled */
 public void testReleaseShared() {
   final BooleanLatch l = new BooleanLatch();
   assertFalse(l.isSignalled());
   assertTrue(l.releaseShared(0));
   assertTrue(l.isSignalled());
   assertTrue(l.releaseShared(0));
   assertTrue(l.isSignalled());
 }
  /** getState is true when acquired and false when not */
  public void testGetState() {
    final Mutex sync = new Mutex();
    sync.acquire();
    assertTrue(sync.isHeldExclusively());
    sync.release();
    assertFalse(sync.isHeldExclusively());

    final BooleanLatch acquired = new BooleanLatch();
    final BooleanLatch done = new BooleanLatch();
    Thread t =
        newStartedThread(
            new CheckedRunnable() {
              public void realRun() throws InterruptedException {
                sync.acquire();
                assertTrue(acquired.releaseShared(0));
                done.acquireShared(0);
                sync.release();
              }
            });

    acquired.acquireShared(0);
    assertTrue(sync.isHeldExclusively());
    assertTrue(done.releaseShared(0));
    awaitTermination(t);
    assertFalse(sync.isHeldExclusively());
  }
 /** getSharedQueuedThreads returns all shared waiting threads */
 public void testGetSharedQueuedThreads_Shared() {
   final BooleanLatch l = new BooleanLatch();
   assertHasSharedQueuedThreads(l, NO_THREADS);
   Thread t1 =
       newStartedThread(
           new CheckedInterruptedRunnable() {
             public void realRun() throws InterruptedException {
               l.acquireSharedInterruptibly(0);
             }
           });
   waitForQueuedThread(l, t1);
   assertHasSharedQueuedThreads(l, t1);
   Thread t2 =
       newStartedThread(
           new CheckedRunnable() {
             public void realRun() throws InterruptedException {
               l.acquireSharedInterruptibly(0);
             }
           });
   waitForQueuedThread(l, t2);
   assertHasSharedQueuedThreads(l, t1, t2);
   t1.interrupt();
   awaitTermination(t1);
   assertHasSharedQueuedThreads(l, t2);
   assertTrue(l.releaseShared(0));
   awaitTermination(t2);
   assertHasSharedQueuedThreads(l, NO_THREADS);
 }
  /** tryAcquireSharedNanos times out if not released before timeout */
  public void testTryAcquireSharedNanos_Timeout() {
    final BooleanLatch l = new BooleanLatch();
    final BooleanLatch observedQueued = new BooleanLatch();
    final long timeoutMillis = timeoutMillis();
    Thread t =
        newStartedThread(
            new CheckedRunnable() {
              public void realRun() throws InterruptedException {
                assertFalse(l.isSignalled());
                for (long millis = timeoutMillis(); !observedQueued.isSignalled(); millis *= 2) {
                  long nanos = MILLISECONDS.toNanos(millis);
                  long startTime = System.nanoTime();
                  assertFalse(l.tryAcquireSharedNanos(0, nanos));
                  assertTrue(millisElapsedSince(startTime) >= millis);
                }
                assertFalse(l.isSignalled());
              }
            });

    waitForQueuedThread(l, t);
    observedQueued.releaseShared(0);
    assertFalse(l.isSignalled());
    awaitTermination(t);
    assertFalse(l.isSignalled());
  }
  /** tryAcquireSharedNanos returns after release, but not before */
  public void testTryAcquireSharedNanos() {
    final BooleanLatch l = new BooleanLatch();

    Thread t =
        newStartedThread(
            new CheckedRunnable() {
              public void realRun() throws InterruptedException {
                assertFalse(l.isSignalled());
                long nanos = MILLISECONDS.toNanos(2 * LONG_DELAY_MS);
                assertTrue(l.tryAcquireSharedNanos(0, nanos));
                assertTrue(l.isSignalled());
                assertTrue(l.tryAcquireSharedNanos(0, nanos));
                assertTrue(l.isSignalled());
              }
            });

    waitForQueuedThread(l, t);
    assertFalse(l.isSignalled());
    assertThreadStaysAlive(t);
    assertTrue(l.releaseShared(0));
    assertTrue(l.isSignalled());
    awaitTermination(t);
  }
  /** acquireSharedInterruptibly returns after release, but not before */
  public void testAcquireSharedInterruptibly() {
    final BooleanLatch l = new BooleanLatch();

    Thread t =
        newStartedThread(
            new CheckedRunnable() {
              public void realRun() throws InterruptedException {
                assertFalse(l.isSignalled());
                l.acquireSharedInterruptibly(0);
                assertTrue(l.isSignalled());
                l.acquireSharedInterruptibly(0);
                assertTrue(l.isSignalled());
              }
            });

    waitForQueuedThread(l, t);
    assertFalse(l.isSignalled());
    assertThreadStaysAlive(t);
    assertHasSharedQueuedThreads(l, t);
    assertTrue(l.releaseShared(0));
    assertTrue(l.isSignalled());
    awaitTermination(t);
  }