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 
9 package jsr166;
10 
11 import junit.framework.*;
12 import java.util.*;
13 import java.util.concurrent.CountDownLatch;
14 import java.util.concurrent.Exchanger;
15 import java.util.concurrent.TimeoutException;
16 import static java.util.concurrent.TimeUnit.MILLISECONDS;
17 
18 public class ExchangerTest extends JSR166TestCase {
19 
20     /**
21      * exchange exchanges objects across two threads
22      */
testExchange()23     public void testExchange() {
24         final Exchanger e = new Exchanger();
25         Thread t1 = newStartedThread(new CheckedRunnable() {
26             public void realRun() throws InterruptedException {
27                 assertSame(one, e.exchange(two));
28                 assertSame(two, e.exchange(one));
29             }});
30         Thread t2 = newStartedThread(new CheckedRunnable() {
31             public void realRun() throws InterruptedException {
32                 assertSame(two, e.exchange(one));
33                 assertSame(one, e.exchange(two));
34             }});
35 
36         awaitTermination(t1);
37         awaitTermination(t2);
38     }
39 
40     /**
41      * timed exchange exchanges objects across two threads
42      */
testTimedExchange()43     public void testTimedExchange() {
44         final Exchanger e = new Exchanger();
45         Thread t1 = newStartedThread(new CheckedRunnable() {
46             public void realRun() throws Exception {
47                 assertSame(one, e.exchange(two, LONG_DELAY_MS, MILLISECONDS));
48                 assertSame(two, e.exchange(one, LONG_DELAY_MS, MILLISECONDS));
49             }});
50         Thread t2 = newStartedThread(new CheckedRunnable() {
51             public void realRun() throws Exception {
52                 assertSame(two, e.exchange(one, LONG_DELAY_MS, MILLISECONDS));
53                 assertSame(one, e.exchange(two, LONG_DELAY_MS, MILLISECONDS));
54             }});
55 
56         awaitTermination(t1);
57         awaitTermination(t2);
58     }
59 
60     /**
61      * interrupt during wait for exchange throws IE
62      */
testExchange_InterruptedException()63     public void testExchange_InterruptedException() {
64         final Exchanger e = new Exchanger();
65         final CountDownLatch threadStarted = new CountDownLatch(1);
66         Thread t = newStartedThread(new CheckedInterruptedRunnable() {
67             public void realRun() throws InterruptedException {
68                 threadStarted.countDown();
69                 e.exchange(one);
70             }});
71 
72         await(threadStarted);
73         t.interrupt();
74         awaitTermination(t);
75     }
76 
77     /**
78      * interrupt during wait for timed exchange throws IE
79      */
testTimedExchange_InterruptedException()80     public void testTimedExchange_InterruptedException() {
81         final Exchanger e = new Exchanger();
82         final CountDownLatch threadStarted = new CountDownLatch(1);
83         Thread t = newStartedThread(new CheckedInterruptedRunnable() {
84             public void realRun() throws Exception {
85                 threadStarted.countDown();
86                 e.exchange(null, LONG_DELAY_MS, MILLISECONDS);
87             }});
88 
89         await(threadStarted);
90         t.interrupt();
91         awaitTermination(t);
92     }
93 
94     /**
95      * timeout during wait for timed exchange throws TimeoutException
96      */
testExchange_TimeoutException()97     public void testExchange_TimeoutException() {
98         final Exchanger e = new Exchanger();
99         Thread t = newStartedThread(new CheckedRunnable() {
100             public void realRun() throws Exception {
101                 long startTime = System.nanoTime();
102                 try {
103                     e.exchange(null, timeoutMillis(), MILLISECONDS);
104                     shouldThrow();
105                 } catch (TimeoutException success) {}
106                 assertTrue(millisElapsedSince(startTime) >= timeoutMillis());
107             }});
108 
109         awaitTermination(t);
110     }
111 
112     /**
113      * If one exchanging thread is interrupted, another succeeds.
114      */
testReplacementAfterExchange()115     public void testReplacementAfterExchange() {
116         final Exchanger e = new Exchanger();
117         final CountDownLatch exchanged = new CountDownLatch(2);
118         final CountDownLatch interrupted = new CountDownLatch(1);
119         Thread t1 = newStartedThread(new CheckedInterruptedRunnable() {
120             public void realRun() throws InterruptedException {
121                 assertSame(two, e.exchange(one));
122                 exchanged.countDown();
123                 e.exchange(two);
124             }});
125         Thread t2 = newStartedThread(new CheckedRunnable() {
126             public void realRun() throws InterruptedException {
127                 assertSame(one, e.exchange(two));
128                 exchanged.countDown();
129                 interrupted.await();
130                 assertSame(three, e.exchange(one));
131             }});
132         Thread t3 = newStartedThread(new CheckedRunnable() {
133             public void realRun() throws InterruptedException {
134                 interrupted.await();
135                 assertSame(one, e.exchange(three));
136             }});
137 
138         await(exchanged);
139         t1.interrupt();
140         awaitTermination(t1);
141         interrupted.countDown();
142         awaitTermination(t2);
143         awaitTermination(t3);
144     }
145 
146 }
147