ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/test/tck/AbstractQueuedSynchronizerTest.java
(Generate patch)

Comparing jsr166/src/test/tck/AbstractQueuedSynchronizerTest.java (file contents):
Revision 1.63 by jsr166, Tue Jan 23 20:44:11 2018 UTC vs.
Revision 1.71 by jsr166, Thu Aug 15 16:01:30 2019 UTC

# Line 13 | Line 13 | import java.util.ArrayList;
13   import java.util.Arrays;
14   import java.util.Collection;
15   import java.util.HashSet;
16 import java.util.concurrent.ThreadLocalRandom;
16   import java.util.concurrent.locks.AbstractQueuedSynchronizer;
17   import java.util.concurrent.locks.AbstractQueuedSynchronizer.ConditionObject;
18  
# Line 228 | Line 227 | public class AbstractQueuedSynchronizerT
227              assertTrue(c.await(timeoutMillis, MILLISECONDS));
228              break;
229          case awaitNanos:
230 <            long nanosTimeout = MILLISECONDS.toNanos(timeoutMillis);
231 <            long nanosRemaining = c.awaitNanos(nanosTimeout);
230 >            long timeoutNanos = MILLISECONDS.toNanos(timeoutMillis);
231 >            long nanosRemaining = c.awaitNanos(timeoutNanos);
232              assertTrue(nanosRemaining > 0);
233              break;
234          case awaitUntil:
# Line 256 | Line 255 | public class AbstractQueuedSynchronizerT
255                  break;
256              case awaitNanos:
257                  startTime = System.nanoTime();
258 <                long nanosTimeout = MILLISECONDS.toNanos(timeoutMillis);
259 <                long nanosRemaining = c.awaitNanos(nanosTimeout);
258 >                long timeoutNanos = MILLISECONDS.toNanos(timeoutMillis);
259 >                long nanosRemaining = c.awaitNanos(timeoutNanos);
260                  assertTrue(nanosRemaining <= 0);
261                  assertTrue(nanosRemaining > -MILLISECONDS.toNanos(LONG_DELAY_MS));
262                  assertTrue(millisElapsedSince(startTime) >= timeoutMillis);
# Line 1283 | Line 1282 | public class AbstractQueuedSynchronizerT
1282              try {
1283                  s.acquireInterruptibly(1);
1284                  shouldThrow();
1285 <            } catch (InterruptedException expected) {}
1285 >            } catch (InterruptedException success) {}
1286          };
1287          for (int i = 0; i < 2; i++) {
1288              Thread thread = new Thread(failedAcquire);
# Line 1310 | Line 1309 | public class AbstractQueuedSynchronizerT
1309      /**
1310       * Tests scenario for
1311       * JDK-8191937: Lost interrupt in AbstractQueuedSynchronizer when tryAcquire methods throw
1312 +     * ant -Djsr166.tckTestClass=AbstractQueuedSynchronizerTest -Djsr166.methodFilter=testInterruptedFailingAcquire -Djsr166.runsPerTest=10000 tck
1313       */
1314 <    public void testInterruptedFailingAcquire() throws InterruptedException {
1315 <        final RuntimeException ex = new RuntimeException();
1314 >    public void testInterruptedFailingAcquire() throws Throwable {
1315 >        class PleaseThrow extends RuntimeException {}
1316 >        final PleaseThrow ex = new PleaseThrow();
1317  
1318          // A synchronizer only offering a choice of failure modes
1319          class Sync extends AbstractQueuedSynchronizer {
1320 <            boolean pleaseThrow;
1320 >            volatile boolean pleaseThrow;
1321              @Override protected boolean tryAcquire(int ignored) {
1322                  if (pleaseThrow) throw ex;
1323                  return false;
# Line 1334 | Line 1335 | public class AbstractQueuedSynchronizerT
1335          }
1336  
1337          final Sync s = new Sync();
1338 <
1338 >        final boolean acquireInterruptibly = randomBoolean();
1339 >        final Action[] uninterruptibleAcquireActions = {
1340 >            () -> s.acquire(1),
1341 >            () -> s.acquireShared(1),
1342 >        };
1343 >        final long nanosTimeout = MILLISECONDS.toNanos(2 * LONG_DELAY_MS);
1344 >        final Action[] interruptibleAcquireActions = {
1345 >            () -> s.acquireInterruptibly(1),
1346 >            () -> s.acquireSharedInterruptibly(1),
1347 >            () -> s.tryAcquireNanos(1, nanosTimeout),
1348 >            () -> s.tryAcquireSharedNanos(1, nanosTimeout),
1349 >        };
1350 >        final Action[] releaseActions = {
1351 >            () -> s.release(1),
1352 >            () -> s.releaseShared(1),
1353 >        };
1354 >        final Action acquireAction = acquireInterruptibly
1355 >            ? chooseRandomly(interruptibleAcquireActions)
1356 >            : chooseRandomly(uninterruptibleAcquireActions);
1357 >        final Action releaseAction
1358 >            = chooseRandomly(releaseActions);
1359 >
1360 >        // From os_posix.cpp:
1361 >        //
1362 >        // NOTE that since there is no "lock" around the interrupt and
1363 >        // is_interrupted operations, there is the possibility that the
1364 >        // interrupted flag (in osThread) will be "false" but that the
1365 >        // low-level events will be in the signaled state. This is
1366 >        // intentional. The effect of this is that Object.wait() and
1367 >        // LockSupport.park() will appear to have a spurious wakeup, which
1368 >        // is allowed and not harmful, and the possibility is so rare that
1369 >        // it is not worth the added complexity to add yet another lock.
1370          final Thread thread = newStartedThread(new CheckedRunnable() {
1371 <            public void realRun() {
1371 >            public void realRun() throws Throwable {
1372                  try {
1373 <                    if (ThreadLocalRandom.current().nextBoolean())
1342 <                        s.acquire(1);
1343 <                    else
1344 <                        s.acquireShared(1);
1373 >                    acquireAction.run();
1374                      shouldThrow();
1375 <                } catch (Throwable t) {
1376 <                    assertSame(ex, t);
1377 <                    assertTrue(Thread.interrupted());
1375 >                } catch (InterruptedException possible) {
1376 >                    assertTrue(acquireInterruptibly);
1377 >                    assertFalse(Thread.interrupted());
1378 >                } catch (PleaseThrow possible) {
1379 >                    awaitInterrupted();
1380                  }
1381              }});
1382 <        waitForThreadToEnterWaitState(thread);
1383 <        assertSame(thread, s.getFirstQueuedThread());
1384 <        assertTrue(s.hasQueuedPredecessors());
1385 <        assertTrue(s.hasQueuedThreads());
1386 <        assertEquals(1, s.getQueueLength());
1382 >        for (long startTime = 0L;; ) {
1383 >            waitForThreadToEnterWaitState(thread);
1384 >            if (s.getFirstQueuedThread() == thread
1385 >                && s.hasQueuedPredecessors()
1386 >                && s.hasQueuedThreads()
1387 >                && s.getQueueLength() == 1)
1388 >                break;
1389 >            if (startTime == 0L)
1390 >                startTime = System.nanoTime();
1391 >            else if (millisElapsedSince(startTime) > LONG_DELAY_MS)
1392 >                fail("timed out waiting for AQS state: "
1393 >                     + "thread state=" + thread.getState()
1394 >                     + ", queued threads=" + s.getQueuedThreads());
1395 >            Thread.yield();
1396 >        }
1397  
1398          s.pleaseThrow = true;
1399 <        thread.interrupt();
1400 <        s.release(1);
1399 >        // release and interrupt, in random order
1400 >        if (randomBoolean()) {
1401 >            thread.interrupt();
1402 >            releaseAction.run();
1403 >        } else {
1404 >            releaseAction.run();
1405 >            thread.interrupt();
1406 >        }
1407          awaitTermination(thread);
1408 +
1409 +        assertNull(s.getFirstQueuedThread());
1410 +        assertFalse(s.hasQueuedPredecessors());
1411 +        assertFalse(s.hasQueuedThreads());
1412 +        assertEquals(0, s.getQueueLength());
1413 +        assertTrue(s.getQueuedThreads().isEmpty());
1414      }
1415  
1416   }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines