test/jdk/java/util/concurrent/tck/AbstractQueuedLongSynchronizerTest.java
changeset 58138 1e4270f875ee
parent 50764 5637aca18f1d
equal deleted inserted replaced
58137:6a556bcd94fc 58138:1e4270f875ee
    37 import static java.util.concurrent.TimeUnit.NANOSECONDS;
    37 import static java.util.concurrent.TimeUnit.NANOSECONDS;
    38 
    38 
    39 import java.util.Arrays;
    39 import java.util.Arrays;
    40 import java.util.Collection;
    40 import java.util.Collection;
    41 import java.util.HashSet;
    41 import java.util.HashSet;
    42 import java.util.concurrent.ThreadLocalRandom;
    42 import java.util.concurrent.atomic.AtomicBoolean;
    43 import java.util.concurrent.locks.AbstractQueuedLongSynchronizer;
    43 import java.util.concurrent.locks.AbstractQueuedLongSynchronizer;
    44 import java.util.concurrent.locks.AbstractQueuedLongSynchronizer.ConditionObject;
    44 import java.util.concurrent.locks.AbstractQueuedLongSynchronizer.ConditionObject;
    45 
    45 
    46 import junit.framework.Test;
    46 import junit.framework.Test;
    47 import junit.framework.TestSuite;
    47 import junit.framework.TestSuite;
  1284     }
  1284     }
  1285 
  1285 
  1286     /**
  1286     /**
  1287      * Tests scenario for
  1287      * Tests scenario for
  1288      * JDK-8191937: Lost interrupt in AbstractQueuedSynchronizer when tryAcquire methods throw
  1288      * JDK-8191937: Lost interrupt in AbstractQueuedSynchronizer when tryAcquire methods throw
  1289      */
  1289      * ant -Djsr166.tckTestClass=AbstractQueuedLongSynchronizerTest -Djsr166.methodFilter=testInterruptedFailingAcquire -Djsr166.runsPerTest=10000 tck
  1290     public void testInterruptedFailingAcquire() throws InterruptedException {
  1290      */
  1291         final RuntimeException ex = new RuntimeException();
  1291     public void testInterruptedFailingAcquire() throws Throwable {
       
  1292         class PleaseThrow extends RuntimeException {}
       
  1293         final PleaseThrow ex = new PleaseThrow();
       
  1294         final AtomicBoolean thrown = new AtomicBoolean();
  1292 
  1295 
  1293         // A synchronizer only offering a choice of failure modes
  1296         // A synchronizer only offering a choice of failure modes
  1294         class Sync extends AbstractQueuedLongSynchronizer {
  1297         class Sync extends AbstractQueuedLongSynchronizer {
  1295             boolean pleaseThrow;
  1298             volatile boolean pleaseThrow;
       
  1299             void maybeThrow() {
       
  1300                 if (pleaseThrow) {
       
  1301                     // assert: tryAcquire methods can throw at most once
       
  1302                     if (! thrown.compareAndSet(false, true))
       
  1303                         throw new AssertionError();
       
  1304                     throw ex;
       
  1305                 }
       
  1306             }
       
  1307 
  1296             @Override protected boolean tryAcquire(long ignored) {
  1308             @Override protected boolean tryAcquire(long ignored) {
  1297                 if (pleaseThrow) throw ex;
  1309                 maybeThrow();
  1298                 return false;
  1310                 return false;
  1299             }
  1311             }
  1300             @Override protected long tryAcquireShared(long ignored) {
  1312             @Override protected long tryAcquireShared(long ignored) {
  1301                 if (pleaseThrow) throw ex;
  1313                 maybeThrow();
  1302                 return -1;
  1314                 return -1;
  1303             }
  1315             }
  1304             @Override protected boolean tryRelease(long ignored) {
  1316             @Override protected boolean tryRelease(long ignored) {
  1305                 return true;
  1317                 return true;
  1306             }
  1318             }
  1308                 return true;
  1320                 return true;
  1309             }
  1321             }
  1310         }
  1322         }
  1311 
  1323 
  1312         final Sync s = new Sync();
  1324         final Sync s = new Sync();
  1313 
  1325         final boolean acquireInterruptibly = randomBoolean();
       
  1326         final Action[] uninterruptibleAcquireActions = {
       
  1327             () -> s.acquire(1),
       
  1328             () -> s.acquireShared(1),
       
  1329         };
       
  1330         final long nanosTimeout = MILLISECONDS.toNanos(2 * LONG_DELAY_MS);
       
  1331         final Action[] interruptibleAcquireActions = {
       
  1332             () -> s.acquireInterruptibly(1),
       
  1333             () -> s.acquireSharedInterruptibly(1),
       
  1334             () -> s.tryAcquireNanos(1, nanosTimeout),
       
  1335             () -> s.tryAcquireSharedNanos(1, nanosTimeout),
       
  1336         };
       
  1337         final Action[] releaseActions = {
       
  1338             () -> s.release(1),
       
  1339             () -> s.releaseShared(1),
       
  1340         };
       
  1341         final Action acquireAction = acquireInterruptibly
       
  1342             ? chooseRandomly(interruptibleAcquireActions)
       
  1343             : chooseRandomly(uninterruptibleAcquireActions);
       
  1344         final Action releaseAction
       
  1345             = chooseRandomly(releaseActions);
       
  1346 
       
  1347         // From os_posix.cpp:
       
  1348         //
       
  1349         // NOTE that since there is no "lock" around the interrupt and
       
  1350         // is_interrupted operations, there is the possibility that the
       
  1351         // interrupted flag (in osThread) will be "false" but that the
       
  1352         // low-level events will be in the signaled state. This is
       
  1353         // intentional. The effect of this is that Object.wait() and
       
  1354         // LockSupport.park() will appear to have a spurious wakeup, which
       
  1355         // is allowed and not harmful, and the possibility is so rare that
       
  1356         // it is not worth the added complexity to add yet another lock.
  1314         final Thread thread = newStartedThread(new CheckedRunnable() {
  1357         final Thread thread = newStartedThread(new CheckedRunnable() {
  1315             public void realRun() {
  1358             public void realRun() throws Throwable {
  1316                 try {
  1359                 try {
  1317                     if (ThreadLocalRandom.current().nextBoolean())
  1360                     acquireAction.run();
  1318                         s.acquire(1);
       
  1319                     else
       
  1320                         s.acquireShared(1);
       
  1321                     shouldThrow();
  1361                     shouldThrow();
  1322                 } catch (Throwable t) {
  1362                 } catch (InterruptedException possible) {
  1323                     assertSame(ex, t);
  1363                     assertTrue(acquireInterruptibly);
  1324                     assertTrue(Thread.interrupted());
  1364                     assertFalse(Thread.interrupted());
       
  1365                 } catch (PleaseThrow possible) {
       
  1366                     awaitInterrupted();
  1325                 }
  1367                 }
  1326             }});
  1368             }});
  1327         waitForThreadToEnterWaitState(thread);
  1369         for (long startTime = 0L;; ) {
  1328         assertSame(thread, s.getFirstQueuedThread());
  1370             waitForThreadToEnterWaitState(thread);
  1329         assertTrue(s.hasQueuedPredecessors());
  1371             if (s.getFirstQueuedThread() == thread
  1330         assertTrue(s.hasQueuedThreads());
  1372                 && s.hasQueuedPredecessors()
  1331         assertEquals(1, s.getQueueLength());
  1373                 && s.hasQueuedThreads()
       
  1374                 && s.getQueueLength() == 1
       
  1375                 && s.hasContended())
       
  1376                 break;
       
  1377             if (startTime == 0L)
       
  1378                 startTime = System.nanoTime();
       
  1379             else if (millisElapsedSince(startTime) > LONG_DELAY_MS)
       
  1380                 fail("timed out waiting for AQS state: "
       
  1381                      + "thread state=" + thread.getState()
       
  1382                      + ", queued threads=" + s.getQueuedThreads());
       
  1383             Thread.yield();
       
  1384         }
  1332 
  1385 
  1333         s.pleaseThrow = true;
  1386         s.pleaseThrow = true;
  1334         thread.interrupt();
  1387         // release and interrupt, in random order
  1335         s.release(1);
  1388         if (randomBoolean()) {
       
  1389             thread.interrupt();
       
  1390             releaseAction.run();
       
  1391         } else {
       
  1392             releaseAction.run();
       
  1393             thread.interrupt();
       
  1394         }
  1336         awaitTermination(thread);
  1395         awaitTermination(thread);
       
  1396 
       
  1397         if (! acquireInterruptibly)
       
  1398             assertTrue(thrown.get());
       
  1399 
       
  1400         assertNull(s.getFirstQueuedThread());
       
  1401         assertFalse(s.hasQueuedPredecessors());
       
  1402         assertFalse(s.hasQueuedThreads());
       
  1403         assertEquals(0, s.getQueueLength());
       
  1404         assertTrue(s.getQueuedThreads().isEmpty());
       
  1405         assertTrue(s.hasContended());
  1337     }
  1406     }
  1338 
  1407 
  1339 }
  1408 }