22
23 /*
24 * This file is available under and governed by the GNU General Public
25 * License version 2 only, as published by the Free Software Foundation.
26 * However, the following notice accompanied the original version of this
27 * file:
28 *
29 * Written by Doug Lea with assistance from members of JCP JSR-166
30 * Expert Group and released to the public domain, as explained at
31 * http://creativecommons.org/publicdomain/zero/1.0/
32 * Other contributors include Andrew Wright, Jeffrey Hayes,
33 * Pat Fisher, Mike Judd.
34 */
35
36 import static java.util.concurrent.TimeUnit.MILLISECONDS;
37 import static java.util.concurrent.TimeUnit.NANOSECONDS;
38
39 import java.util.Arrays;
40 import java.util.Collection;
41 import java.util.HashSet;
42 import java.util.concurrent.ThreadLocalRandom;
43 import java.util.concurrent.locks.AbstractQueuedLongSynchronizer;
44 import java.util.concurrent.locks.AbstractQueuedLongSynchronizer.ConditionObject;
45
46 import junit.framework.Test;
47 import junit.framework.TestSuite;
48
49 @SuppressWarnings("WaitNotInLoop") // we implement spurious-wakeup freedom
50 public class AbstractQueuedLongSynchronizerTest extends JSR166TestCase {
51 public static void main(String[] args) {
52 main(suite(), args);
53 }
54 public static Test suite() {
55 return new TestSuite(AbstractQueuedLongSynchronizerTest.class);
56 }
57
58 /**
59 * A simple mutex class, adapted from the class javadoc. Exclusive
60 * acquire tests exercise this as a sample user extension.
61 *
62 * Unlike the javadoc sample, we don't track owner thread via
1269 assertTrue(c.awaitNanos(0L) <= 0);
1270 assertFalse(c.await(0L, NANOSECONDS));
1271 sync.release();
1272 }
1273
1274 /**
1275 * awaitNanos/timed await with maximum negative wait times does not underflow
1276 */
1277 public void testAwait_NegativeInfinity() throws InterruptedException {
1278 final Mutex sync = new Mutex();
1279 final ConditionObject c = sync.newCondition();
1280 sync.acquire();
1281 assertTrue(c.awaitNanos(Long.MIN_VALUE) <= 0);
1282 assertFalse(c.await(Long.MIN_VALUE, NANOSECONDS));
1283 sync.release();
1284 }
1285
1286 /**
1287 * Tests scenario for
1288 * JDK-8191937: Lost interrupt in AbstractQueuedSynchronizer when tryAcquire methods throw
1289 */
1290 public void testInterruptedFailingAcquire() throws InterruptedException {
1291 final RuntimeException ex = new RuntimeException();
1292
1293 // A synchronizer only offering a choice of failure modes
1294 class Sync extends AbstractQueuedLongSynchronizer {
1295 boolean pleaseThrow;
1296 @Override protected boolean tryAcquire(long ignored) {
1297 if (pleaseThrow) throw ex;
1298 return false;
1299 }
1300 @Override protected long tryAcquireShared(long ignored) {
1301 if (pleaseThrow) throw ex;
1302 return -1;
1303 }
1304 @Override protected boolean tryRelease(long ignored) {
1305 return true;
1306 }
1307 @Override protected boolean tryReleaseShared(long ignored) {
1308 return true;
1309 }
1310 }
1311
1312 final Sync s = new Sync();
1313
1314 final Thread thread = newStartedThread(new CheckedRunnable() {
1315 public void realRun() {
1316 try {
1317 if (ThreadLocalRandom.current().nextBoolean())
1318 s.acquire(1);
1319 else
1320 s.acquireShared(1);
1321 shouldThrow();
1322 } catch (Throwable t) {
1323 assertSame(ex, t);
1324 assertTrue(Thread.interrupted());
1325 }
1326 }});
1327 waitForThreadToEnterWaitState(thread);
1328 assertSame(thread, s.getFirstQueuedThread());
1329 assertTrue(s.hasQueuedPredecessors());
1330 assertTrue(s.hasQueuedThreads());
1331 assertEquals(1, s.getQueueLength());
1332
1333 s.pleaseThrow = true;
1334 thread.interrupt();
1335 s.release(1);
1336 awaitTermination(thread);
1337 }
1338
1339 }
|
22
23 /*
24 * This file is available under and governed by the GNU General Public
25 * License version 2 only, as published by the Free Software Foundation.
26 * However, the following notice accompanied the original version of this
27 * file:
28 *
29 * Written by Doug Lea with assistance from members of JCP JSR-166
30 * Expert Group and released to the public domain, as explained at
31 * http://creativecommons.org/publicdomain/zero/1.0/
32 * Other contributors include Andrew Wright, Jeffrey Hayes,
33 * Pat Fisher, Mike Judd.
34 */
35
36 import static java.util.concurrent.TimeUnit.MILLISECONDS;
37 import static java.util.concurrent.TimeUnit.NANOSECONDS;
38
39 import java.util.Arrays;
40 import java.util.Collection;
41 import java.util.HashSet;
42 import java.util.concurrent.atomic.AtomicBoolean;
43 import java.util.concurrent.locks.AbstractQueuedLongSynchronizer;
44 import java.util.concurrent.locks.AbstractQueuedLongSynchronizer.ConditionObject;
45
46 import junit.framework.Test;
47 import junit.framework.TestSuite;
48
49 @SuppressWarnings("WaitNotInLoop") // we implement spurious-wakeup freedom
50 public class AbstractQueuedLongSynchronizerTest extends JSR166TestCase {
51 public static void main(String[] args) {
52 main(suite(), args);
53 }
54 public static Test suite() {
55 return new TestSuite(AbstractQueuedLongSynchronizerTest.class);
56 }
57
58 /**
59 * A simple mutex class, adapted from the class javadoc. Exclusive
60 * acquire tests exercise this as a sample user extension.
61 *
62 * Unlike the javadoc sample, we don't track owner thread via
1269 assertTrue(c.awaitNanos(0L) <= 0);
1270 assertFalse(c.await(0L, NANOSECONDS));
1271 sync.release();
1272 }
1273
1274 /**
1275 * awaitNanos/timed await with maximum negative wait times does not underflow
1276 */
1277 public void testAwait_NegativeInfinity() throws InterruptedException {
1278 final Mutex sync = new Mutex();
1279 final ConditionObject c = sync.newCondition();
1280 sync.acquire();
1281 assertTrue(c.awaitNanos(Long.MIN_VALUE) <= 0);
1282 assertFalse(c.await(Long.MIN_VALUE, NANOSECONDS));
1283 sync.release();
1284 }
1285
1286 /**
1287 * Tests scenario for
1288 * JDK-8191937: Lost interrupt in AbstractQueuedSynchronizer when tryAcquire methods throw
1289 * ant -Djsr166.tckTestClass=AbstractQueuedLongSynchronizerTest -Djsr166.methodFilter=testInterruptedFailingAcquire -Djsr166.runsPerTest=10000 tck
1290 */
1291 public void testInterruptedFailingAcquire() throws Throwable {
1292 class PleaseThrow extends RuntimeException {}
1293 final PleaseThrow ex = new PleaseThrow();
1294 final AtomicBoolean thrown = new AtomicBoolean();
1295
1296 // A synchronizer only offering a choice of failure modes
1297 class Sync extends AbstractQueuedLongSynchronizer {
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
1308 @Override protected boolean tryAcquire(long ignored) {
1309 maybeThrow();
1310 return false;
1311 }
1312 @Override protected long tryAcquireShared(long ignored) {
1313 maybeThrow();
1314 return -1;
1315 }
1316 @Override protected boolean tryRelease(long ignored) {
1317 return true;
1318 }
1319 @Override protected boolean tryReleaseShared(long ignored) {
1320 return true;
1321 }
1322 }
1323
1324 final Sync s = new Sync();
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.
1357 final Thread thread = newStartedThread(new CheckedRunnable() {
1358 public void realRun() throws Throwable {
1359 try {
1360 acquireAction.run();
1361 shouldThrow();
1362 } catch (InterruptedException possible) {
1363 assertTrue(acquireInterruptibly);
1364 assertFalse(Thread.interrupted());
1365 } catch (PleaseThrow possible) {
1366 awaitInterrupted();
1367 }
1368 }});
1369 for (long startTime = 0L;; ) {
1370 waitForThreadToEnterWaitState(thread);
1371 if (s.getFirstQueuedThread() == thread
1372 && s.hasQueuedPredecessors()
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 }
1385
1386 s.pleaseThrow = true;
1387 // release and interrupt, in random order
1388 if (randomBoolean()) {
1389 thread.interrupt();
1390 releaseAction.run();
1391 } else {
1392 releaseAction.run();
1393 thread.interrupt();
1394 }
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());
1406 }
1407
1408 }
|