/** 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);
 }
  /** 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);
  }
 /**
  * Waits for the specified time (in milliseconds) for the thread to terminate (using {@link
  * Thread#join(long)}), else interrupts the thread (in the hope that it may terminate later) and
  * fails.
  */
 void awaitTermination(Thread t, long timeoutMillis) {
   try {
     t.join(timeoutMillis);
   } catch (InterruptedException ie) {
     threadUnexpectedException(ie);
   } finally {
     if (t.getState() != Thread.State.TERMINATED) {
       t.interrupt();
       fail("Test timed out");
     }
   }
 }
  /** tryAcquireNanos is interruptible */
  public void testTryAcquireNanos_Interruptible() {
    final Mutex sync = new Mutex();
    sync.acquire();
    Thread t =
        newStartedThread(
            new CheckedInterruptedRunnable() {
              public void realRun() throws InterruptedException {
                sync.tryAcquireNanos(MILLISECONDS.toNanos(2 * LONG_DELAY_MS));
              }
            });

    waitForQueuedThread(sync, t);
    t.interrupt();
    awaitTermination(t);
  }
 /** getFirstQueuedThread returns first waiting thread or null if none */
 public void testGetFirstQueuedThread() {
   final Mutex sync = new Mutex();
   assertNull(sync.getFirstQueuedThread());
   sync.acquire();
   Thread t1 = newStartedThread(new InterruptedSyncRunnable(sync));
   waitForQueuedThread(sync, t1);
   assertEquals(t1, sync.getFirstQueuedThread());
   Thread t2 = newStartedThread(new InterruptibleSyncRunnable(sync));
   waitForQueuedThread(sync, t2);
   assertEquals(t1, sync.getFirstQueuedThread());
   t1.interrupt();
   awaitTermination(t1);
   assertEquals(t2, sync.getFirstQueuedThread());
   sync.release();
   awaitTermination(t2);
   assertNull(sync.getFirstQueuedThread());
 }
 /** hasQueuedThreads reports whether there are waiting threads */
 public void testHasQueuedThreads() {
   final Mutex sync = new Mutex();
   assertFalse(sync.hasQueuedThreads());
   sync.acquire();
   Thread t1 = newStartedThread(new InterruptedSyncRunnable(sync));
   waitForQueuedThread(sync, t1);
   assertTrue(sync.hasQueuedThreads());
   Thread t2 = newStartedThread(new InterruptibleSyncRunnable(sync));
   waitForQueuedThread(sync, t2);
   assertTrue(sync.hasQueuedThreads());
   t1.interrupt();
   awaitTermination(t1);
   assertTrue(sync.hasQueuedThreads());
   sync.release();
   awaitTermination(t2);
   assertFalse(sync.hasQueuedThreads());
 }
  /** acquireSharedInterruptibly is interruptible */
  public void testAcquireSharedInterruptibly_Interruptible() {
    final BooleanLatch l = new BooleanLatch();
    Thread t =
        newStartedThread(
            new CheckedInterruptedRunnable() {
              public void realRun() throws InterruptedException {
                assertFalse(l.isSignalled());
                l.acquireSharedInterruptibly(0);
              }
            });

    waitForQueuedThread(l, t);
    assertFalse(l.isSignalled());
    t.interrupt();
    awaitTermination(t);
    assertFalse(l.isSignalled());
  }
  public void testInterruptible(final AwaitMethod awaitMethod) {
    final Mutex sync = new Mutex();
    final ConditionObject c = sync.newCondition();
    final BooleanLatch pleaseInterrupt = new BooleanLatch();
    Thread t =
        newStartedThread(
            new CheckedInterruptedRunnable() {
              public void realRun() throws InterruptedException {
                sync.acquire();
                assertTrue(pleaseInterrupt.releaseShared(0));
                await(c, awaitMethod);
              }
            });

    pleaseInterrupt.acquireShared(0);
    t.interrupt();
    awaitTermination(t);
  }
 /** getSharedQueuedThreads does not include exclusively waiting threads */
 public void testGetSharedQueuedThreads_Exclusive() {
   final Mutex sync = new Mutex();
   assertTrue(sync.getSharedQueuedThreads().isEmpty());
   sync.acquire();
   assertTrue(sync.getSharedQueuedThreads().isEmpty());
   Thread t1 = newStartedThread(new InterruptedSyncRunnable(sync));
   waitForQueuedThread(sync, t1);
   assertTrue(sync.getSharedQueuedThreads().isEmpty());
   Thread t2 = newStartedThread(new InterruptibleSyncRunnable(sync));
   waitForQueuedThread(sync, t2);
   assertTrue(sync.getSharedQueuedThreads().isEmpty());
   t1.interrupt();
   awaitTermination(t1);
   assertTrue(sync.getSharedQueuedThreads().isEmpty());
   sync.release();
   awaitTermination(t2);
   assertTrue(sync.getSharedQueuedThreads().isEmpty());
 }
  /** tryAcquireSharedNanos is interruptible */
  public void testTryAcquireSharedNanos_Interruptible() {
    final BooleanLatch l = new BooleanLatch();
    Thread t =
        newStartedThread(
            new CheckedInterruptedRunnable() {
              public void realRun() throws InterruptedException {
                assertFalse(l.isSignalled());
                long nanos = MILLISECONDS.toNanos(2 * LONG_DELAY_MS);
                l.tryAcquireSharedNanos(0, nanos);
              }
            });

    waitForQueuedThread(l, t);
    assertFalse(l.isSignalled());
    t.interrupt();
    awaitTermination(t);
    assertFalse(l.isSignalled());
  }
  /** acquireInterruptibly succeeds when released, else is interruptible */
  public void testAcquireInterruptibly() throws InterruptedException {
    final Mutex sync = new Mutex();
    final BooleanLatch threadStarted = new BooleanLatch();
    sync.acquireInterruptibly();
    Thread t =
        newStartedThread(
            new CheckedInterruptedRunnable() {
              public void realRun() throws InterruptedException {
                assertTrue(threadStarted.releaseShared(0));
                sync.acquireInterruptibly();
              }
            });

    threadStarted.acquireShared(0);
    waitForQueuedThread(sync, t);
    t.interrupt();
    awaitTermination(t);
    assertTrue(sync.isHeldExclusively());
  }
  /** A serialized AQS deserializes with current state, but no queued threads */
  public void testSerialization() {
    Mutex sync = new Mutex();
    assertFalse(serialClone(sync).isHeldExclusively());
    sync.acquire();
    Thread t = newStartedThread(new InterruptedSyncRunnable(sync));
    waitForQueuedThread(sync, t);
    assertTrue(sync.isHeldExclusively());

    Mutex clone = serialClone(sync);
    assertTrue(clone.isHeldExclusively());
    assertHasExclusiveQueuedThreads(sync, t);
    assertHasExclusiveQueuedThreads(clone, NO_THREADS);
    t.interrupt();
    awaitTermination(t);
    sync.release();
    assertFalse(sync.isHeldExclusively());
    assertTrue(clone.isHeldExclusively());
    assertHasExclusiveQueuedThreads(sync, NO_THREADS);
    assertHasExclusiveQueuedThreads(clone, NO_THREADS);
  }
 /** getExclusiveQueuedThreads returns all exclusive waiting threads */
 public void testGetExclusiveQueuedThreads() {
   final Mutex sync = new Mutex();
   Thread t1 = new Thread(new InterruptedSyncRunnable(sync));
   Thread t2 = new Thread(new InterruptibleSyncRunnable(sync));
   assertHasExclusiveQueuedThreads(sync, NO_THREADS);
   sync.acquire();
   assertHasExclusiveQueuedThreads(sync, NO_THREADS);
   t1.start();
   waitForQueuedThread(sync, t1);
   assertHasExclusiveQueuedThreads(sync, t1);
   assertTrue(sync.getExclusiveQueuedThreads().contains(t1));
   assertFalse(sync.getExclusiveQueuedThreads().contains(t2));
   t2.start();
   waitForQueuedThread(sync, t2);
   assertHasExclusiveQueuedThreads(sync, t1, t2);
   assertTrue(sync.getExclusiveQueuedThreads().contains(t1));
   assertTrue(sync.getExclusiveQueuedThreads().contains(t2));
   t1.interrupt();
   awaitTermination(t1);
   assertHasExclusiveQueuedThreads(sync, t2);
   sync.release();
   awaitTermination(t2);
   assertHasExclusiveQueuedThreads(sync, NO_THREADS);
 }