| /* |
| * Written by Doug Lea with assistance from members of JCP JSR-166 |
| * Expert Group and released to the public domain, as explained at |
| * http://creativecommons.org/publicdomain/zero/1.0/ |
| * Other contributors include John Vint |
| */ |
| |
| package jsr166; |
| |
| import static java.util.concurrent.TimeUnit.MILLISECONDS; |
| |
| import java.util.ArrayList; |
| import java.util.List; |
| import java.util.concurrent.CountDownLatch; |
| import java.util.concurrent.Phaser; |
| import java.util.concurrent.TimeoutException; |
| import java.util.concurrent.atomic.AtomicInteger; |
| |
| import junit.framework.Test; |
| import junit.framework.TestSuite; |
| |
| public class PhaserTest extends JSR166TestCase { |
| |
| // android-note: Removed because the CTS runner does a bad job of |
| // retrying tests that have suite() declarations. |
| // |
| // public static void main(String[] args) { |
| // main(suite(), args); |
| // } |
| // public static Test suite() { |
| // return new TestSuite(PhaserTest.class); |
| // } |
| |
| private static final int maxParties = 65535; |
| |
| /** Checks state of unterminated phaser. */ |
| protected void assertState(Phaser phaser, |
| int phase, int parties, int unarrived) { |
| assertEquals(phase, phaser.getPhase()); |
| assertEquals(parties, phaser.getRegisteredParties()); |
| assertEquals(unarrived, phaser.getUnarrivedParties()); |
| assertEquals(parties - unarrived, phaser.getArrivedParties()); |
| assertFalse(phaser.isTerminated()); |
| } |
| |
| /** Checks state of terminated phaser. */ |
| protected void assertTerminated(Phaser phaser, int maxPhase, int parties) { |
| assertTrue(phaser.isTerminated()); |
| int expectedPhase = maxPhase + Integer.MIN_VALUE; |
| assertEquals(expectedPhase, phaser.getPhase()); |
| assertEquals(parties, phaser.getRegisteredParties()); |
| assertEquals(expectedPhase, phaser.register()); |
| assertEquals(expectedPhase, phaser.arrive()); |
| assertEquals(expectedPhase, phaser.arriveAndDeregister()); |
| } |
| |
| protected void assertTerminated(Phaser phaser, int maxPhase) { |
| assertTerminated(phaser, maxPhase, 0); |
| } |
| |
| /** |
| * Empty constructor builds a new Phaser with no parent, no registered |
| * parties and initial phase number of 0 |
| */ |
| public void testConstructorDefaultValues() { |
| Phaser phaser = new Phaser(); |
| assertNull(phaser.getParent()); |
| assertEquals(0, phaser.getRegisteredParties()); |
| assertEquals(0, phaser.getArrivedParties()); |
| assertEquals(0, phaser.getUnarrivedParties()); |
| assertEquals(0, phaser.getPhase()); |
| } |
| |
| /** |
| * Constructing with a negative number of parties throws |
| * IllegalArgumentException |
| */ |
| public void testConstructorNegativeParties() { |
| try { |
| new Phaser(-1); |
| shouldThrow(); |
| } catch (IllegalArgumentException success) {} |
| } |
| |
| /** |
| * Constructing with a negative number of parties throws |
| * IllegalArgumentException |
| */ |
| public void testConstructorNegativeParties2() { |
| try { |
| new Phaser(new Phaser(), -1); |
| shouldThrow(); |
| } catch (IllegalArgumentException success) {} |
| } |
| |
| /** |
| * Constructing with a number of parties > 65535 throws |
| * IllegalArgumentException |
| */ |
| public void testConstructorPartiesExceedsLimit() { |
| new Phaser(maxParties); |
| try { |
| new Phaser(maxParties + 1); |
| shouldThrow(); |
| } catch (IllegalArgumentException success) {} |
| |
| new Phaser(new Phaser(), maxParties); |
| try { |
| new Phaser(new Phaser(), maxParties + 1); |
| shouldThrow(); |
| } catch (IllegalArgumentException success) {} |
| } |
| |
| /** |
| * The parent provided to the constructor should be returned from |
| * a later call to getParent |
| */ |
| public void testConstructor3() { |
| Phaser parent = new Phaser(); |
| assertSame(parent, new Phaser(parent).getParent()); |
| assertNull(new Phaser(null).getParent()); |
| } |
| |
| /** |
| * The parent being input into the parameter should equal the original |
| * parent when being returned |
| */ |
| public void testConstructor5() { |
| Phaser parent = new Phaser(); |
| assertSame(parent, new Phaser(parent, 0).getParent()); |
| assertNull(new Phaser(null, 0).getParent()); |
| } |
| |
| /** |
| * register() will increment the number of unarrived parties by |
| * one and not affect its arrived parties |
| */ |
| public void testRegister1() { |
| Phaser phaser = new Phaser(); |
| assertState(phaser, 0, 0, 0); |
| assertEquals(0, phaser.register()); |
| assertState(phaser, 0, 1, 1); |
| } |
| |
| /** |
| * Registering more than 65536 parties causes IllegalStateException |
| */ |
| public void testRegister2() { |
| Phaser phaser = new Phaser(0); |
| assertState(phaser, 0, 0, 0); |
| assertEquals(0, phaser.bulkRegister(maxParties - 10)); |
| assertState(phaser, 0, maxParties - 10, maxParties - 10); |
| for (int i = 0; i < 10; i++) { |
| assertState(phaser, 0, maxParties - 10 + i, maxParties - 10 + i); |
| assertEquals(0, phaser.register()); |
| } |
| assertState(phaser, 0, maxParties, maxParties); |
| try { |
| phaser.register(); |
| shouldThrow(); |
| } catch (IllegalStateException success) {} |
| |
| try { |
| phaser.bulkRegister(Integer.MAX_VALUE); |
| shouldThrow(); |
| } catch (IllegalStateException success) {} |
| |
| assertEquals(0, phaser.bulkRegister(0)); |
| assertState(phaser, 0, maxParties, maxParties); |
| } |
| |
| /** |
| * register() correctly returns the current barrier phase number |
| * when invoked |
| */ |
| public void testRegister3() { |
| Phaser phaser = new Phaser(); |
| assertEquals(0, phaser.register()); |
| assertEquals(0, phaser.arrive()); |
| assertEquals(1, phaser.register()); |
| assertState(phaser, 1, 2, 2); |
| } |
| |
| /** |
| * register causes the next arrive to not increment the phase |
| * rather retain the phase number |
| */ |
| public void testRegister4() { |
| Phaser phaser = new Phaser(1); |
| assertEquals(0, phaser.arrive()); |
| assertEquals(1, phaser.register()); |
| assertEquals(1, phaser.arrive()); |
| assertState(phaser, 1, 2, 1); |
| } |
| |
| /** |
| * register on a subphaser that is currently empty succeeds, even |
| * in the presence of another non-empty subphaser |
| */ |
| public void testRegisterEmptySubPhaser() { |
| Phaser root = new Phaser(); |
| Phaser child1 = new Phaser(root, 1); |
| Phaser child2 = new Phaser(root, 0); |
| assertEquals(0, child2.register()); |
| assertState(root, 0, 2, 2); |
| assertState(child1, 0, 1, 1); |
| assertState(child2, 0, 1, 1); |
| assertEquals(0, child2.arriveAndDeregister()); |
| assertState(root, 0, 1, 1); |
| assertState(child1, 0, 1, 1); |
| assertState(child2, 0, 0, 0); |
| assertEquals(0, child2.register()); |
| assertEquals(0, child2.arriveAndDeregister()); |
| assertState(root, 0, 1, 1); |
| assertState(child1, 0, 1, 1); |
| assertState(child2, 0, 0, 0); |
| assertEquals(0, child1.arriveAndDeregister()); |
| assertTerminated(root, 1); |
| assertTerminated(child1, 1); |
| assertTerminated(child2, 1); |
| } |
| |
| /** |
| * Invoking bulkRegister with a negative parameter throws an |
| * IllegalArgumentException |
| */ |
| public void testBulkRegister1() { |
| try { |
| new Phaser().bulkRegister(-1); |
| shouldThrow(); |
| } catch (IllegalArgumentException success) {} |
| } |
| |
| /** |
| * bulkRegister should correctly record the number of unarrived |
| * parties with the number of parties being registered |
| */ |
| public void testBulkRegister2() { |
| Phaser phaser = new Phaser(); |
| assertEquals(0, phaser.bulkRegister(0)); |
| assertState(phaser, 0, 0, 0); |
| assertEquals(0, phaser.bulkRegister(20)); |
| assertState(phaser, 0, 20, 20); |
| } |
| |
| /** |
| * Registering with a number of parties greater than or equal to 1<<16 |
| * throws IllegalStateException. |
| */ |
| public void testBulkRegister3() { |
| assertEquals(0, new Phaser().bulkRegister((1 << 16) - 1)); |
| |
| try { |
| new Phaser().bulkRegister(1 << 16); |
| shouldThrow(); |
| } catch (IllegalStateException success) {} |
| |
| try { |
| new Phaser(2).bulkRegister((1 << 16) - 2); |
| shouldThrow(); |
| } catch (IllegalStateException success) {} |
| } |
| |
| /** |
| * the phase number increments correctly when tripping the barrier |
| */ |
| public void testPhaseIncrement1() { |
| for (int size = 1; size < nine; size++) { |
| final Phaser phaser = new Phaser(size); |
| for (int index = 0; index <= (1 << size); index++) { |
| int phase = phaser.arrive(); |
| assertTrue(index % size == 0 ? (index / size) == phase : index - (phase * size) > 0); |
| } |
| } |
| } |
| |
| /** |
| * arrive() on a registered phaser increments phase. |
| */ |
| public void testArrive1() { |
| Phaser phaser = new Phaser(1); |
| assertState(phaser, 0, 1, 1); |
| assertEquals(0, phaser.arrive()); |
| assertState(phaser, 1, 1, 1); |
| } |
| |
| /** |
| * arriveAndDeregister does not wait for others to arrive at barrier |
| */ |
| public void testArriveAndDeregister() { |
| final Phaser phaser = new Phaser(1); |
| for (int i = 0; i < 10; i++) { |
| assertState(phaser, 0, 1, 1); |
| assertEquals(0, phaser.register()); |
| assertState(phaser, 0, 2, 2); |
| assertEquals(0, phaser.arriveAndDeregister()); |
| assertState(phaser, 0, 1, 1); |
| } |
| assertEquals(0, phaser.arriveAndDeregister()); |
| assertTerminated(phaser, 1); |
| } |
| |
| /** |
| * arriveAndDeregister does not wait for others to arrive at barrier |
| */ |
| public void testArrive2() { |
| final Phaser phaser = new Phaser(); |
| assertEquals(0, phaser.register()); |
| List<Thread> threads = new ArrayList<Thread>(); |
| for (int i = 0; i < 10; i++) { |
| assertEquals(0, phaser.register()); |
| threads.add(newStartedThread(new CheckedRunnable() { |
| public void realRun() { |
| assertEquals(0, phaser.arriveAndDeregister()); |
| }})); |
| } |
| |
| for (Thread thread : threads) |
| awaitTermination(thread); |
| assertState(phaser, 0, 1, 1); |
| assertEquals(0, phaser.arrive()); |
| assertState(phaser, 1, 1, 1); |
| } |
| |
| /** |
| * arrive() returns a negative number if the Phaser is terminated |
| */ |
| public void testArrive3() { |
| Phaser phaser = new Phaser(1); |
| phaser.forceTermination(); |
| assertTerminated(phaser, 0, 1); |
| assertEquals(0, phaser.getPhase() + Integer.MIN_VALUE); |
| assertTrue(phaser.arrive() < 0); |
| assertTrue(phaser.register() < 0); |
| assertTrue(phaser.arriveAndDeregister() < 0); |
| assertTrue(phaser.awaitAdvance(1) < 0); |
| assertTrue(phaser.getPhase() < 0); |
| } |
| |
| /** |
| * arriveAndDeregister() throws IllegalStateException if number of |
| * registered or unarrived parties would become negative |
| */ |
| public void testArriveAndDeregister1() { |
| Phaser phaser = new Phaser(); |
| try { |
| phaser.arriveAndDeregister(); |
| shouldThrow(); |
| } catch (IllegalStateException success) {} |
| } |
| |
| /** |
| * arriveAndDeregister reduces the number of arrived parties |
| */ |
| public void testArriveAndDeregister2() { |
| final Phaser phaser = new Phaser(1); |
| assertEquals(0, phaser.register()); |
| assertEquals(0, phaser.arrive()); |
| assertState(phaser, 0, 2, 1); |
| assertEquals(0, phaser.arriveAndDeregister()); |
| assertState(phaser, 1, 1, 1); |
| } |
| |
| /** |
| * arriveAndDeregister arrives at the barrier on a phaser with a parent and |
| * when a deregistration occurs and causes the phaser to have zero parties |
| * its parent will be deregistered as well |
| */ |
| public void testArriveAndDeregister3() { |
| Phaser parent = new Phaser(); |
| Phaser child = new Phaser(parent); |
| assertState(child, 0, 0, 0); |
| assertState(parent, 0, 0, 0); |
| assertEquals(0, child.register()); |
| assertState(child, 0, 1, 1); |
| assertState(parent, 0, 1, 1); |
| assertEquals(0, child.arriveAndDeregister()); |
| assertTerminated(child, 1); |
| assertTerminated(parent, 1); |
| } |
| |
| /** |
| * arriveAndDeregister deregisters one party from its parent when |
| * the number of parties of child is zero after deregistration |
| */ |
| public void testArriveAndDeregister4() { |
| Phaser parent = new Phaser(); |
| Phaser child = new Phaser(parent); |
| assertEquals(0, parent.register()); |
| assertEquals(0, child.register()); |
| assertState(child, 0, 1, 1); |
| assertState(parent, 0, 2, 2); |
| assertEquals(0, child.arriveAndDeregister()); |
| assertState(child, 0, 0, 0); |
| assertState(parent, 0, 1, 1); |
| } |
| |
| /** |
| * arriveAndDeregister deregisters one party from its parent when |
| * the number of parties of root is nonzero after deregistration. |
| */ |
| public void testArriveAndDeregister5() { |
| Phaser root = new Phaser(); |
| Phaser parent = new Phaser(root); |
| Phaser child = new Phaser(parent); |
| assertState(root, 0, 0, 0); |
| assertState(parent, 0, 0, 0); |
| assertState(child, 0, 0, 0); |
| assertEquals(0, child.register()); |
| assertState(root, 0, 1, 1); |
| assertState(parent, 0, 1, 1); |
| assertState(child, 0, 1, 1); |
| assertEquals(0, child.arriveAndDeregister()); |
| assertTerminated(child, 1); |
| assertTerminated(parent, 1); |
| assertTerminated(root, 1); |
| } |
| |
| /** |
| * arriveAndDeregister returns the phase in which it leaves the |
| * phaser in after deregistration |
| */ |
| public void testArriveAndDeregister6() { |
| final Phaser phaser = new Phaser(2); |
| Thread t = newStartedThread(new CheckedRunnable() { |
| public void realRun() { |
| assertEquals(0, phaser.arrive()); |
| }}); |
| assertEquals(1, phaser.arriveAndAwaitAdvance()); |
| assertState(phaser, 1, 2, 2); |
| assertEquals(1, phaser.arriveAndDeregister()); |
| assertState(phaser, 1, 1, 1); |
| assertEquals(1, phaser.arriveAndDeregister()); |
| assertTerminated(phaser, 2); |
| awaitTermination(t); |
| } |
| |
| /** |
| * awaitAdvance succeeds upon advance |
| */ |
| public void testAwaitAdvance1() { |
| final Phaser phaser = new Phaser(1); |
| assertEquals(0, phaser.arrive()); |
| assertEquals(1, phaser.awaitAdvance(0)); |
| } |
| |
| /** |
| * awaitAdvance with a negative parameter will return without affecting the |
| * phaser |
| */ |
| public void testAwaitAdvance2() { |
| Phaser phaser = new Phaser(); |
| assertTrue(phaser.awaitAdvance(-1) < 0); |
| assertState(phaser, 0, 0, 0); |
| } |
| |
| /** |
| * awaitAdvanceInterruptibly blocks interruptibly |
| */ |
| public void testAwaitAdvanceInterruptibly_interruptible() throws InterruptedException { |
| final Phaser phaser = new Phaser(1); |
| final CountDownLatch pleaseInterrupt = new CountDownLatch(2); |
| |
| Thread t1 = newStartedThread(new CheckedRunnable() { |
| public void realRun() { |
| Thread.currentThread().interrupt(); |
| try { |
| phaser.awaitAdvanceInterruptibly(0); |
| shouldThrow(); |
| } catch (InterruptedException success) {} |
| assertFalse(Thread.interrupted()); |
| |
| pleaseInterrupt.countDown(); |
| try { |
| phaser.awaitAdvanceInterruptibly(0); |
| shouldThrow(); |
| } catch (InterruptedException success) {} |
| assertFalse(Thread.interrupted()); |
| }}); |
| |
| Thread t2 = newStartedThread(new CheckedRunnable() { |
| public void realRun() throws TimeoutException { |
| Thread.currentThread().interrupt(); |
| try { |
| phaser.awaitAdvanceInterruptibly(0, 2*LONG_DELAY_MS, MILLISECONDS); |
| shouldThrow(); |
| } catch (InterruptedException success) {} |
| assertFalse(Thread.interrupted()); |
| |
| pleaseInterrupt.countDown(); |
| try { |
| phaser.awaitAdvanceInterruptibly(0, 2*LONG_DELAY_MS, MILLISECONDS); |
| shouldThrow(); |
| } catch (InterruptedException success) {} |
| assertFalse(Thread.interrupted()); |
| }}); |
| |
| await(pleaseInterrupt); |
| assertState(phaser, 0, 1, 1); |
| assertThreadsStayAlive(t1, t2); |
| t1.interrupt(); |
| t2.interrupt(); |
| awaitTermination(t1); |
| awaitTermination(t2); |
| assertState(phaser, 0, 1, 1); |
| assertEquals(0, phaser.arrive()); |
| assertState(phaser, 1, 1, 1); |
| } |
| |
| /** |
| * awaitAdvance continues waiting if interrupted before waiting |
| */ |
| public void testAwaitAdvanceAfterInterrupt() { |
| final Phaser phaser = new Phaser(); |
| assertEquals(0, phaser.register()); |
| final CountDownLatch pleaseArrive = new CountDownLatch(1); |
| |
| Thread t = newStartedThread(new CheckedRunnable() { |
| public void realRun() { |
| Thread.currentThread().interrupt(); |
| assertEquals(0, phaser.register()); |
| assertEquals(0, phaser.arrive()); |
| pleaseArrive.countDown(); |
| assertTrue(Thread.currentThread().isInterrupted()); |
| assertEquals(1, phaser.awaitAdvance(0)); |
| assertTrue(Thread.interrupted()); |
| }}); |
| |
| await(pleaseArrive); |
| waitForThreadToEnterWaitState(t); |
| assertEquals(0, phaser.arrive()); |
| awaitTermination(t); |
| |
| Thread.currentThread().interrupt(); |
| assertEquals(1, phaser.awaitAdvance(0)); |
| assertTrue(Thread.interrupted()); |
| } |
| |
| /** |
| * awaitAdvance continues waiting if interrupted while waiting |
| */ |
| public void testAwaitAdvanceBeforeInterrupt() { |
| final Phaser phaser = new Phaser(); |
| assertEquals(0, phaser.register()); |
| final CountDownLatch pleaseArrive = new CountDownLatch(1); |
| |
| Thread t = newStartedThread(new CheckedRunnable() { |
| public void realRun() { |
| assertEquals(0, phaser.register()); |
| assertEquals(0, phaser.arrive()); |
| assertFalse(Thread.currentThread().isInterrupted()); |
| pleaseArrive.countDown(); |
| assertEquals(1, phaser.awaitAdvance(0)); |
| assertTrue(Thread.interrupted()); |
| }}); |
| |
| await(pleaseArrive); |
| waitForThreadToEnterWaitState(t); |
| t.interrupt(); |
| assertEquals(0, phaser.arrive()); |
| awaitTermination(t); |
| |
| Thread.currentThread().interrupt(); |
| assertEquals(1, phaser.awaitAdvance(0)); |
| assertTrue(Thread.interrupted()); |
| } |
| |
| /** |
| * arriveAndAwaitAdvance continues waiting if interrupted before waiting |
| */ |
| public void testArriveAndAwaitAdvanceAfterInterrupt() { |
| final Phaser phaser = new Phaser(); |
| assertEquals(0, phaser.register()); |
| final CountDownLatch pleaseArrive = new CountDownLatch(1); |
| |
| Thread t = newStartedThread(new CheckedRunnable() { |
| public void realRun() { |
| Thread.currentThread().interrupt(); |
| assertEquals(0, phaser.register()); |
| pleaseArrive.countDown(); |
| assertTrue(Thread.currentThread().isInterrupted()); |
| assertEquals(1, phaser.arriveAndAwaitAdvance()); |
| assertTrue(Thread.interrupted()); |
| }}); |
| |
| await(pleaseArrive); |
| waitForThreadToEnterWaitState(t); |
| Thread.currentThread().interrupt(); |
| assertEquals(1, phaser.arriveAndAwaitAdvance()); |
| assertTrue(Thread.interrupted()); |
| awaitTermination(t); |
| } |
| |
| /** |
| * arriveAndAwaitAdvance continues waiting if interrupted while waiting |
| */ |
| public void testArriveAndAwaitAdvanceBeforeInterrupt() { |
| final Phaser phaser = new Phaser(); |
| assertEquals(0, phaser.register()); |
| final CountDownLatch pleaseInterrupt = new CountDownLatch(1); |
| |
| Thread t = newStartedThread(new CheckedRunnable() { |
| public void realRun() { |
| assertEquals(0, phaser.register()); |
| assertFalse(Thread.currentThread().isInterrupted()); |
| pleaseInterrupt.countDown(); |
| assertEquals(1, phaser.arriveAndAwaitAdvance()); |
| assertTrue(Thread.interrupted()); |
| }}); |
| |
| await(pleaseInterrupt); |
| waitForThreadToEnterWaitState(t); |
| t.interrupt(); |
| Thread.currentThread().interrupt(); |
| assertEquals(1, phaser.arriveAndAwaitAdvance()); |
| assertTrue(Thread.interrupted()); |
| awaitTermination(t); |
| } |
| |
| /** |
| * awaitAdvance atomically waits for all parties within the same phase to |
| * complete before continuing |
| */ |
| public void testAwaitAdvance4() { |
| final Phaser phaser = new Phaser(4); |
| final AtomicInteger count = new AtomicInteger(0); |
| List<Thread> threads = new ArrayList<Thread>(); |
| for (int i = 0; i < 4; i++) |
| threads.add(newStartedThread(new CheckedRunnable() { |
| public void realRun() { |
| for (int k = 0; k < 3; k++) { |
| assertEquals(2 * k + 1, phaser.arriveAndAwaitAdvance()); |
| count.incrementAndGet(); |
| assertEquals(2 * k + 1, phaser.arrive()); |
| assertEquals(2 * k + 2, phaser.awaitAdvance(2 * k + 1)); |
| assertEquals(4 * (k + 1), count.get()); |
| }}})); |
| |
| for (Thread thread : threads) |
| awaitTermination(thread); |
| } |
| |
| /** |
| * awaitAdvance returns the current phase |
| */ |
| public void testAwaitAdvance5() { |
| final Phaser phaser = new Phaser(1); |
| assertEquals(1, phaser.awaitAdvance(phaser.arrive())); |
| assertEquals(1, phaser.getPhase()); |
| assertEquals(1, phaser.register()); |
| List<Thread> threads = new ArrayList<Thread>(); |
| for (int i = 0; i < 8; i++) { |
| final CountDownLatch latch = new CountDownLatch(1); |
| final boolean goesFirst = ((i & 1) == 0); |
| threads.add(newStartedThread(new CheckedRunnable() { |
| public void realRun() { |
| if (goesFirst) |
| latch.countDown(); |
| else |
| await(latch); |
| phaser.arrive(); |
| }})); |
| if (goesFirst) |
| await(latch); |
| else |
| latch.countDown(); |
| assertEquals(i + 2, phaser.awaitAdvance(phaser.arrive())); |
| assertEquals(i + 2, phaser.getPhase()); |
| } |
| for (Thread thread : threads) |
| awaitTermination(thread); |
| } |
| |
| /** |
| * awaitAdvance returns the current phase in child phasers |
| */ |
| public void testAwaitAdvanceTieredPhaser() throws Exception { |
| final Phaser parent = new Phaser(); |
| final List<Phaser> zeroPartyChildren = new ArrayList<Phaser>(3); |
| final List<Phaser> onePartyChildren = new ArrayList<Phaser>(3); |
| for (int i = 0; i < 3; i++) { |
| zeroPartyChildren.add(new Phaser(parent, 0)); |
| onePartyChildren.add(new Phaser(parent, 1)); |
| } |
| final List<Phaser> phasers = new ArrayList<Phaser>(); |
| phasers.addAll(zeroPartyChildren); |
| phasers.addAll(onePartyChildren); |
| phasers.add(parent); |
| for (Phaser phaser : phasers) { |
| assertEquals(-42, phaser.awaitAdvance(-42)); |
| assertEquals(-42, phaser.awaitAdvanceInterruptibly(-42)); |
| assertEquals(-42, phaser.awaitAdvanceInterruptibly(-42, MEDIUM_DELAY_MS, MILLISECONDS)); |
| } |
| |
| for (Phaser child : onePartyChildren) |
| assertEquals(0, child.arrive()); |
| for (Phaser phaser : phasers) { |
| assertEquals(-42, phaser.awaitAdvance(-42)); |
| assertEquals(-42, phaser.awaitAdvanceInterruptibly(-42)); |
| assertEquals(-42, phaser.awaitAdvanceInterruptibly(-42, MEDIUM_DELAY_MS, MILLISECONDS)); |
| assertEquals(1, phaser.awaitAdvance(0)); |
| assertEquals(1, phaser.awaitAdvanceInterruptibly(0)); |
| assertEquals(1, phaser.awaitAdvanceInterruptibly(0, MEDIUM_DELAY_MS, MILLISECONDS)); |
| } |
| |
| for (Phaser child : onePartyChildren) |
| assertEquals(1, child.arrive()); |
| for (Phaser phaser : phasers) { |
| assertEquals(-42, phaser.awaitAdvance(-42)); |
| assertEquals(-42, phaser.awaitAdvanceInterruptibly(-42)); |
| assertEquals(-42, phaser.awaitAdvanceInterruptibly(-42, MEDIUM_DELAY_MS, MILLISECONDS)); |
| assertEquals(2, phaser.awaitAdvance(0)); |
| assertEquals(2, phaser.awaitAdvanceInterruptibly(0)); |
| assertEquals(2, phaser.awaitAdvanceInterruptibly(0, MEDIUM_DELAY_MS, MILLISECONDS)); |
| assertEquals(2, phaser.awaitAdvance(1)); |
| assertEquals(2, phaser.awaitAdvanceInterruptibly(1)); |
| assertEquals(2, phaser.awaitAdvanceInterruptibly(1, MEDIUM_DELAY_MS, MILLISECONDS)); |
| } |
| } |
| |
| /** |
| * awaitAdvance returns when the phaser is externally terminated |
| */ |
| public void testAwaitAdvance6() { |
| final Phaser phaser = new Phaser(3); |
| final CountDownLatch pleaseForceTermination = new CountDownLatch(2); |
| final List<Thread> threads = new ArrayList<Thread>(); |
| for (int i = 0; i < 2; i++) { |
| Runnable r = new CheckedRunnable() { |
| public void realRun() { |
| assertEquals(0, phaser.arrive()); |
| pleaseForceTermination.countDown(); |
| assertTrue(phaser.awaitAdvance(0) < 0); |
| assertTrue(phaser.isTerminated()); |
| assertTrue(phaser.getPhase() < 0); |
| assertEquals(0, phaser.getPhase() + Integer.MIN_VALUE); |
| assertEquals(3, phaser.getRegisteredParties()); |
| }}; |
| threads.add(newStartedThread(r)); |
| } |
| await(pleaseForceTermination); |
| phaser.forceTermination(); |
| assertTrue(phaser.isTerminated()); |
| assertEquals(0, phaser.getPhase() + Integer.MIN_VALUE); |
| for (Thread thread : threads) |
| awaitTermination(thread); |
| assertEquals(3, phaser.getRegisteredParties()); |
| } |
| |
| /** |
| * arriveAndAwaitAdvance throws IllegalStateException with no |
| * unarrived parties |
| */ |
| public void testArriveAndAwaitAdvance1() { |
| Phaser phaser = new Phaser(); |
| try { |
| phaser.arriveAndAwaitAdvance(); |
| shouldThrow(); |
| } catch (IllegalStateException success) {} |
| } |
| |
| /** |
| * arriveAndAwaitAdvance waits for all threads to arrive, the |
| * number of arrived parties is the same number that is accounted |
| * for when the main thread awaitsAdvance |
| */ |
| public void testArriveAndAwaitAdvance3() { |
| final Phaser phaser = new Phaser(1); |
| final int THREADS = 3; |
| final CountDownLatch pleaseArrive = new CountDownLatch(THREADS); |
| final List<Thread> threads = new ArrayList<Thread>(); |
| for (int i = 0; i < THREADS; i++) |
| threads.add(newStartedThread(new CheckedRunnable() { |
| public void realRun() { |
| assertEquals(0, phaser.register()); |
| pleaseArrive.countDown(); |
| assertEquals(1, phaser.arriveAndAwaitAdvance()); |
| }})); |
| |
| await(pleaseArrive); |
| long startTime = System.nanoTime(); |
| while (phaser.getArrivedParties() < THREADS) |
| Thread.yield(); |
| assertEquals(THREADS, phaser.getArrivedParties()); |
| assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS); |
| for (Thread thread : threads) |
| waitForThreadToEnterWaitState(thread); |
| for (Thread thread : threads) |
| assertTrue(thread.isAlive()); |
| assertState(phaser, 0, THREADS + 1, 1); |
| phaser.arriveAndAwaitAdvance(); |
| for (Thread thread : threads) |
| awaitTermination(thread); |
| assertState(phaser, 1, THREADS + 1, THREADS + 1); |
| } |
| |
| } |