1/*
2 * Written by Doug Lea with assistance from members of JCP JSR-166
3 * Expert Group and released to the public domain, as explained at
4 * http://creativecommons.org/publicdomain/zero/1.0/
5 * Other contributors include Andrew Wright, Jeffrey Hayes,
6 * Pat Fisher, Mike Judd.
7 */
8
9package jsr166;
10
11import static java.util.concurrent.TimeUnit.MILLISECONDS;
12
13import java.util.concurrent.CountDownLatch;
14import java.util.concurrent.Exchanger;
15import java.util.concurrent.TimeoutException;
16
17import junit.framework.Test;
18import junit.framework.TestSuite;
19
20public class ExchangerTest extends JSR166TestCase {
21
22    // android-note: Removed because the CTS runner does a bad job of
23    // retrying tests that have suite() declarations.
24    //
25    // public static void main(String[] args) {
26    //     main(suite(), args);
27    // }
28    // public static Test suite() {
29    //     return new TestSuite(ExchangerTest.class);
30    // }
31
32    /**
33     * exchange exchanges objects across two threads
34     */
35    public void testExchange() {
36        final Exchanger e = new Exchanger();
37        Thread t1 = newStartedThread(new CheckedRunnable() {
38            public void realRun() throws InterruptedException {
39                assertSame(one, e.exchange(two));
40                assertSame(two, e.exchange(one));
41            }});
42        Thread t2 = newStartedThread(new CheckedRunnable() {
43            public void realRun() throws InterruptedException {
44                assertSame(two, e.exchange(one));
45                assertSame(one, e.exchange(two));
46            }});
47
48        awaitTermination(t1);
49        awaitTermination(t2);
50    }
51
52    /**
53     * timed exchange exchanges objects across two threads
54     */
55    public void testTimedExchange() {
56        final Exchanger e = new Exchanger();
57        Thread t1 = newStartedThread(new CheckedRunnable() {
58            public void realRun() throws Exception {
59                assertSame(one, e.exchange(two, LONG_DELAY_MS, MILLISECONDS));
60                assertSame(two, e.exchange(one, LONG_DELAY_MS, MILLISECONDS));
61            }});
62        Thread t2 = newStartedThread(new CheckedRunnable() {
63            public void realRun() throws Exception {
64                assertSame(two, e.exchange(one, LONG_DELAY_MS, MILLISECONDS));
65                assertSame(one, e.exchange(two, LONG_DELAY_MS, MILLISECONDS));
66            }});
67
68        awaitTermination(t1);
69        awaitTermination(t2);
70    }
71
72    /**
73     * interrupt during wait for exchange throws IE
74     */
75    public void testExchange_InterruptedException() {
76        final Exchanger e = new Exchanger();
77        final CountDownLatch threadStarted = new CountDownLatch(1);
78        Thread t = newStartedThread(new CheckedInterruptedRunnable() {
79            public void realRun() throws InterruptedException {
80                threadStarted.countDown();
81                e.exchange(one);
82            }});
83
84        await(threadStarted);
85        t.interrupt();
86        awaitTermination(t);
87    }
88
89    /**
90     * interrupt during wait for timed exchange throws IE
91     */
92    public void testTimedExchange_InterruptedException() {
93        final Exchanger e = new Exchanger();
94        final CountDownLatch threadStarted = new CountDownLatch(1);
95        Thread t = newStartedThread(new CheckedInterruptedRunnable() {
96            public void realRun() throws Exception {
97                threadStarted.countDown();
98                e.exchange(null, LONG_DELAY_MS, MILLISECONDS);
99            }});
100
101        await(threadStarted);
102        t.interrupt();
103        awaitTermination(t);
104    }
105
106    /**
107     * timeout during wait for timed exchange throws TimeoutException
108     */
109    public void testExchange_TimeoutException() {
110        final Exchanger e = new Exchanger();
111        Thread t = newStartedThread(new CheckedRunnable() {
112            public void realRun() throws Exception {
113                long startTime = System.nanoTime();
114                try {
115                    e.exchange(null, timeoutMillis(), MILLISECONDS);
116                    shouldThrow();
117                } catch (TimeoutException success) {}
118                assertTrue(millisElapsedSince(startTime) >= timeoutMillis());
119            }});
120
121        awaitTermination(t);
122    }
123
124    /**
125     * If one exchanging thread is interrupted, another succeeds.
126     */
127    public void testReplacementAfterExchange() {
128        final Exchanger e = new Exchanger();
129        final CountDownLatch exchanged = new CountDownLatch(2);
130        final CountDownLatch interrupted = new CountDownLatch(1);
131        Thread t1 = newStartedThread(new CheckedInterruptedRunnable() {
132            public void realRun() throws InterruptedException {
133                assertSame(two, e.exchange(one));
134                exchanged.countDown();
135                e.exchange(two);
136            }});
137        Thread t2 = newStartedThread(new CheckedRunnable() {
138            public void realRun() throws InterruptedException {
139                assertSame(one, e.exchange(two));
140                exchanged.countDown();
141                interrupted.await();
142                assertSame(three, e.exchange(one));
143            }});
144        Thread t3 = newStartedThread(new CheckedRunnable() {
145            public void realRun() throws InterruptedException {
146                interrupted.await();
147                assertSame(one, e.exchange(three));
148            }});
149
150        await(exchanged);
151        t1.interrupt();
152        awaitTermination(t1);
153        interrupted.countDown();
154        awaitTermination(t2);
155        awaitTermination(t3);
156    }
157
158}
159