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

Comparing jsr166/src/test/tck/CyclicBarrierTest.java (file contents):
Revision 1.1 by dl, Sun Aug 31 19:24:54 2003 UTC vs.
Revision 1.34 by jsr166, Mon Sep 9 00:46:44 2019 UTC

# Line 1 | Line 1
1   /*
2 < * Written by members of JCP JSR-166 Expert Group and released to the
3 < * public domain. Use, modify, and redistribute this code in any way
4 < * without acknowledgement. Other contributors include Andrew Wright,
5 < * Jeffrey Hayes, Pat Fischer, Mike Judd.
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 < import junit.framework.*;
9 < import java.util.*;
10 < import java.util.concurrent.*;
9 > import static java.util.concurrent.TimeUnit.MILLISECONDS;
10  
11 < public class CyclicBarrierTest extends TestCase{
12 <    
11 > import java.util.concurrent.BrokenBarrierException;
12 > import java.util.concurrent.CountDownLatch;
13 > import java.util.concurrent.CyclicBarrier;
14 > import java.util.concurrent.ExecutorService;
15 > import java.util.concurrent.Executors;
16 > import java.util.concurrent.ThreadLocalRandom;
17 > import java.util.concurrent.TimeoutException;
18 > import java.util.concurrent.atomic.AtomicInteger;
19 >
20 > import junit.framework.Test;
21 > import junit.framework.TestSuite;
22 >
23 > public class CyclicBarrierTest extends JSR166TestCase {
24      public static void main(String[] args) {
25 <        junit.textui.TestRunner.run (suite());  
25 >        main(suite(), args);
26      }
17    
18    
27      public static Test suite() {
28 <        return new TestSuite(CyclicBarrierTest.class);
28 >        return new TestSuite(CyclicBarrierTest.class);
29 >    }
30 >
31 >    /**
32 >     * Spin-waits till the number of waiters == numberOfWaiters.
33 >     */
34 >    void awaitNumberWaiting(CyclicBarrier barrier, int numberOfWaiters) {
35 >        long startTime = System.nanoTime();
36 >        while (barrier.getNumberWaiting() != numberOfWaiters) {
37 >            if (millisElapsedSince(startTime) > LONG_DELAY_MS)
38 >                fail("timed out");
39 >            Thread.yield();
40 >        }
41      }
22    
23    private static long SHORT_DELAY_MS = 100;
24    private static long MEDIUM_DELAY_MS = 1000;
25    private static long LONG_DELAY_MS = 10000;
42  
43 <    public void testConstructor1(){
44 <        try{
43 >    /**
44 >     * Creating with negative parties throws IllegalArgumentException
45 >     */
46 >    public void testConstructor1() {
47 >        try {
48              new CyclicBarrier(-1, (Runnable)null);
49 <            fail("should throw");
50 <        } catch(IllegalArgumentException e){}
49 >            shouldThrow();
50 >        } catch (IllegalArgumentException success) {}
51      }
52  
53 <    public void testConstructor2(){
54 <        try{
53 >    /**
54 >     * Creating with negative parties and no action throws
55 >     * IllegalArgumentException
56 >     */
57 >    public void testConstructor2() {
58 >        try {
59              new CyclicBarrier(-1);
60 <            fail("should throw");
61 <        } catch(IllegalArgumentException e){}
60 >            shouldThrow();
61 >        } catch (IllegalArgumentException success) {}
62      }
63  
64 <    public void testConstructor3(){
64 >    /**
65 >     * getParties returns the number of parties given in constructor
66 >     */
67 >    public void testGetParties() {
68          CyclicBarrier b = new CyclicBarrier(2);
69 <        assertEquals(2, b.getParties());
69 >        assertEquals(2, b.getParties());
70          assertEquals(0, b.getNumberWaiting());
71      }
72  
73 <    public void testSingleParty() {
74 <        try {
75 <            CyclicBarrier b = new CyclicBarrier(1);
76 <            assertEquals(1, b.getParties());
77 <            assertEquals(0, b.getNumberWaiting());
78 <            b.await();
79 <            b.await();
80 <            assertEquals(0, b.getNumberWaiting());
81 <        }
82 <        catch(Exception e) {
57 <            fail("unexpected exception");
58 <        }
59 <    }
60 <    
61 <    private volatile int countAction;
62 <    private class MyAction implements Runnable {
63 <        public void run() { ++countAction; }
73 >    /**
74 >     * A 1-party barrier triggers after single await
75 >     */
76 >    public void testSingleParty() throws Exception {
77 >        CyclicBarrier b = new CyclicBarrier(1);
78 >        assertEquals(1, b.getParties());
79 >        assertEquals(0, b.getNumberWaiting());
80 >        b.await();
81 >        b.await();
82 >        assertEquals(0, b.getNumberWaiting());
83      }
84  
85 <    public void testBarrierAction() {
86 <        try {
87 <            countAction = 0;
88 <            CyclicBarrier b = new CyclicBarrier(1, new MyAction());
89 <            assertEquals(1, b.getParties());
90 <            assertEquals(0, b.getNumberWaiting());
91 <            b.await();
92 <            b.await();
93 <            assertEquals(0, b.getNumberWaiting());
94 <            assertEquals(countAction, 2);
95 <        }
96 <        catch(Exception e) {
97 <            fail("unexpected exception");
98 <        }
85 >    /**
86 >     * The supplied barrier action is run at barrier
87 >     */
88 >    public void testBarrierAction() throws Exception {
89 >        final AtomicInteger count = new AtomicInteger(0);
90 >        final Runnable incCount = new Runnable() { public void run() {
91 >            count.getAndIncrement(); }};
92 >        CyclicBarrier b = new CyclicBarrier(1, incCount);
93 >        assertEquals(1, b.getParties());
94 >        assertEquals(0, b.getNumberWaiting());
95 >        b.await();
96 >        b.await();
97 >        assertEquals(0, b.getNumberWaiting());
98 >        assertEquals(2, count.get());
99      }
100  
101 <
102 <    public void testTwoParties(){
101 >    /**
102 >     * A 2-party/thread barrier triggers after both threads invoke await
103 >     */
104 >    public void testTwoParties() throws Exception {
105          final CyclicBarrier b = new CyclicBarrier(2);
106 <        Thread t = new Thread(new Runnable() {
107 <                public void run(){
108 <                    try {
109 <                        b.await();
110 <                        b.await();
111 <                        b.await();
112 <                        b.await();
113 <                    } catch(Exception e){
114 <                        fail("unexpected exception");
115 <                    }}});
106 >        Thread t = newStartedThread(new CheckedRunnable() {
107 >            public void realRun() throws Exception {
108 >                b.await();
109 >                b.await();
110 >                b.await();
111 >                b.await();
112 >            }});
113 >
114 >        b.await();
115 >        b.await();
116 >        b.await();
117 >        b.await();
118 >        awaitTermination(t);
119 >    }
120 >
121 >    /**
122 >     * An interruption in one party causes others waiting in await to
123 >     * throw BrokenBarrierException
124 >     */
125 >    public void testAwait1_Interrupted_BrokenBarrier() {
126 >        final CyclicBarrier c = new CyclicBarrier(3);
127 >        final CountDownLatch pleaseInterrupt = new CountDownLatch(2);
128 >        Thread t1 = new ThreadShouldThrow(InterruptedException.class) {
129 >            public void realRun() throws Exception {
130 >                pleaseInterrupt.countDown();
131 >                c.await();
132 >            }};
133 >        Thread t2 = new ThreadShouldThrow(BrokenBarrierException.class) {
134 >            public void realRun() throws Exception {
135 >                pleaseInterrupt.countDown();
136 >                c.await();
137 >            }};
138 >
139 >        t1.start();
140 >        t2.start();
141 >        await(pleaseInterrupt);
142 >        t1.interrupt();
143 >        awaitTermination(t1);
144 >        awaitTermination(t2);
145 >    }
146 >
147 >    /**
148 >     * An interruption in one party causes others waiting in timed await to
149 >     * throw BrokenBarrierException
150 >     */
151 >    public void testAwait2_Interrupted_BrokenBarrier() throws Exception {
152 >        final CyclicBarrier c = new CyclicBarrier(3);
153 >        final CountDownLatch pleaseInterrupt = new CountDownLatch(2);
154 >        Thread t1 = new ThreadShouldThrow(InterruptedException.class) {
155 >            public void realRun() throws Exception {
156 >                pleaseInterrupt.countDown();
157 >                c.await(LONG_DELAY_MS, MILLISECONDS);
158 >            }};
159 >        Thread t2 = new ThreadShouldThrow(BrokenBarrierException.class) {
160 >            public void realRun() throws Exception {
161 >                pleaseInterrupt.countDown();
162 >                c.await(LONG_DELAY_MS, MILLISECONDS);
163 >            }};
164 >
165 >        t1.start();
166 >        t2.start();
167 >        await(pleaseInterrupt);
168 >        t1.interrupt();
169 >        awaitTermination(t1);
170 >        awaitTermination(t2);
171 >    }
172 >
173 >    /**
174 >     * A timeout in timed await throws TimeoutException
175 >     */
176 >    public void testAwait3_TimeoutException() throws InterruptedException {
177 >        final CyclicBarrier c = new CyclicBarrier(2);
178 >        Thread t = newStartedThread(new CheckedRunnable() {
179 >            public void realRun() throws Exception {
180 >                long startTime = System.nanoTime();
181 >                try {
182 >                    c.await(timeoutMillis(), MILLISECONDS);
183 >                    shouldThrow();
184 >                } catch (TimeoutException success) {}
185 >                assertTrue(millisElapsedSince(startTime) >= timeoutMillis());
186 >            }});
187 >
188 >        awaitTermination(t);
189 >    }
190 >
191 >    /**
192 >     * A timeout in one party causes others waiting in timed await to
193 >     * throw BrokenBarrierException
194 >     */
195 >    public void testAwait4_Timeout_BrokenBarrier() throws InterruptedException {
196 >        final CyclicBarrier c = new CyclicBarrier(3);
197 >        Thread t1 = newStartedThread(new CheckedRunnable() {
198 >            public void realRun() throws Exception {
199 >                try {
200 >                    c.await(LONG_DELAY_MS, MILLISECONDS);
201 >                    shouldThrow();
202 >                } catch (BrokenBarrierException success) {}
203 >            }});
204 >        Thread t2 = newStartedThread(new CheckedRunnable() {
205 >            public void realRun() throws Exception {
206 >                awaitNumberWaiting(c, 1);
207 >                long startTime = System.nanoTime();
208 >                try {
209 >                    c.await(timeoutMillis(), MILLISECONDS);
210 >                    shouldThrow();
211 >                } catch (TimeoutException success) {}
212 >                assertTrue(millisElapsedSince(startTime) >= timeoutMillis());
213 >            }});
214 >
215 >        awaitTermination(t1);
216 >        awaitTermination(t2);
217 >    }
218 >
219 >    /**
220 >     * A timeout in one party causes others waiting in await to
221 >     * throw BrokenBarrierException
222 >     */
223 >    public void testAwait5_Timeout_BrokenBarrier() throws InterruptedException {
224 >        final CyclicBarrier c = new CyclicBarrier(3);
225 >        Thread t1 = newStartedThread(new CheckedRunnable() {
226 >            public void realRun() throws Exception {
227 >                try {
228 >                    c.await();
229 >                    shouldThrow();
230 >                } catch (BrokenBarrierException success) {}
231 >            }});
232 >        Thread t2 = newStartedThread(new CheckedRunnable() {
233 >            public void realRun() throws Exception {
234 >                awaitNumberWaiting(c, 1);
235 >                long startTime = System.nanoTime();
236 >                try {
237 >                    c.await(timeoutMillis(), MILLISECONDS);
238 >                    shouldThrow();
239 >                } catch (TimeoutException success) {}
240 >                assertTrue(millisElapsedSince(startTime) >= timeoutMillis());
241 >            }});
242 >
243 >        awaitTermination(t1);
244 >        awaitTermination(t2);
245 >    }
246 >
247 >    /**
248 >     * A reset of an active barrier causes waiting threads to throw
249 >     * BrokenBarrierException
250 >     */
251 >    public void testReset_BrokenBarrier() throws InterruptedException {
252 >        final CyclicBarrier c = new CyclicBarrier(3);
253 >        final CountDownLatch pleaseReset = new CountDownLatch(2);
254 >        Thread t1 = new ThreadShouldThrow(BrokenBarrierException.class) {
255 >            public void realRun() throws Exception {
256 >                pleaseReset.countDown();
257 >                c.await();
258 >            }};
259 >        Thread t2 = new ThreadShouldThrow(BrokenBarrierException.class) {
260 >            public void realRun() throws Exception {
261 >                pleaseReset.countDown();
262 >                c.await();
263 >            }};
264 >
265 >        t1.start();
266 >        t2.start();
267 >        await(pleaseReset);
268 >
269 >        awaitNumberWaiting(c, 2);
270 >        c.reset();
271 >        awaitTermination(t1);
272 >        awaitTermination(t2);
273 >    }
274 >
275 >    /**
276 >     * A reset before threads enter barrier does not throw
277 >     * BrokenBarrierException
278 >     */
279 >    public void testReset_NoBrokenBarrier() throws Exception {
280 >        final CyclicBarrier c = new CyclicBarrier(3);
281 >        c.reset();
282  
283 <        try {
284 <            t.start();
285 <            b.await();
286 <            b.await();
287 <            b.await();
288 <            b.await();
289 <            t.join();
290 <        } catch(Exception e){
291 <            fail("unexpected exception");
283 >        Thread t1 = newStartedThread(new CheckedRunnable() {
284 >            public void realRun() throws Exception {
285 >                c.await();
286 >            }});
287 >        Thread t2 = newStartedThread(new CheckedRunnable() {
288 >            public void realRun() throws Exception {
289 >                c.await();
290 >            }});
291 >
292 >        c.await();
293 >        awaitTermination(t1);
294 >        awaitTermination(t2);
295 >    }
296 >
297 >    /**
298 >     * Reset of a non-broken barrier does not break barrier
299 >     */
300 >    public void testResetWithoutBreakage() throws Exception {
301 >        final CyclicBarrier barrier = new CyclicBarrier(3);
302 >        for (int i = 0; i < 3; i++) {
303 >            final CyclicBarrier start = new CyclicBarrier(3);
304 >            Thread t1 = newStartedThread(new CheckedRunnable() {
305 >                public void realRun() throws Exception {
306 >                    start.await();
307 >                    barrier.await();
308 >                }});
309 >
310 >            Thread t2 = newStartedThread(new CheckedRunnable() {
311 >                public void realRun() throws Exception {
312 >                    start.await();
313 >                    barrier.await();
314 >                }});
315 >
316 >            start.await();
317 >            barrier.await();
318 >            awaitTermination(t1);
319 >            awaitTermination(t2);
320 >            assertFalse(barrier.isBroken());
321 >            assertEquals(0, barrier.getNumberWaiting());
322 >            if (i == 1) barrier.reset();
323 >            assertFalse(barrier.isBroken());
324 >            assertEquals(0, barrier.getNumberWaiting());
325          }
326      }
327  
328 +    /**
329 +     * Reset of a barrier after interruption reinitializes it.
330 +     */
331 +    public void testResetAfterInterrupt() throws Exception {
332 +        final CyclicBarrier barrier = new CyclicBarrier(3);
333 +        for (int i = 0; i < 2; i++) {
334 +            final CyclicBarrier start = new CyclicBarrier(3);
335 +            Thread t1 = new ThreadShouldThrow(InterruptedException.class) {
336 +                public void realRun() throws Exception {
337 +                    start.await();
338 +                    barrier.await();
339 +                }};
340 +
341 +            Thread t2 = new ThreadShouldThrow(BrokenBarrierException.class) {
342 +                public void realRun() throws Exception {
343 +                    start.await();
344 +                    barrier.await();
345 +                }};
346  
109    public void testAwait1_Interrupted_BrokenBarrier(){
110        final CyclicBarrier c = new CyclicBarrier(3);
111        Thread t1 = new Thread(new Runnable() {
112                public void run(){
113                    try{
114                        c.await();
115                        fail("should throw");
116                    } catch(InterruptedException success){}                
117                    catch(Exception b){
118                        fail("should throw IE");
119                    }
120                }
121            });
122        Thread t2 = new Thread(new Runnable(){
123                public void run(){
124                    try{
125                        c.await();
126                        fail("should throw");                        
127                    } catch(BrokenBarrierException success){
128                    } catch(Exception i){
129                        fail("should throw BBE");
130                    }
131                }
132            });
133        try {
347              t1.start();
348              t2.start();
349 <            Thread.sleep(SHORT_DELAY_MS);
349 >            start.await();
350              t1.interrupt();
351 <            t1.join();
352 <            t2.join();
353 <        } catch(InterruptedException e){
354 <            fail("unexpected exception");
351 >            awaitTermination(t1);
352 >            awaitTermination(t2);
353 >            assertTrue(barrier.isBroken());
354 >            assertEquals(0, barrier.getNumberWaiting());
355 >            barrier.reset();
356 >            assertFalse(barrier.isBroken());
357 >            assertEquals(0, barrier.getNumberWaiting());
358          }
359      }
360  
361 <    public void testAwait2_Interrupted_BrokenBarrier(){
362 <      final CyclicBarrier c = new CyclicBarrier(3);
363 <        Thread t1 = new Thread(new Runnable() {
364 <                public void run(){
365 <                    try{
366 <                        c.await(MEDIUM_DELAY_MS, TimeUnit.MILLISECONDS);
367 <                        fail("should throw");
368 <                    } catch(InterruptedException success){
369 <                    } catch(Exception b){
370 <                        fail("should throw IE");
371 <                    }
372 <                }
373 <            });
374 <        Thread t2 = new Thread(new Runnable(){
375 <                public void run(){
376 <                    try{
377 <                        c.await(MEDIUM_DELAY_MS, TimeUnit.MILLISECONDS);
378 <                        fail("should throw");                        
379 <                    } catch(BrokenBarrierException success){
380 <                    } catch(Exception i){
381 <                        fail("should throw BBE");
382 <                    }
383 <                }
384 <            });
385 <        try {
361 >    /**
362 >     * Reset of a barrier after timeout reinitializes it.
363 >     */
364 >    public void testResetAfterTimeout() throws Exception {
365 >        final CyclicBarrier barrier = new CyclicBarrier(3);
366 >        for (int i = 0; i < 2; i++) {
367 >            assertEquals(0, barrier.getNumberWaiting());
368 >            Thread t1 = newStartedThread(new CheckedRunnable() {
369 >                public void realRun() throws Exception {
370 >                    try {
371 >                        barrier.await();
372 >                        shouldThrow();
373 >                    } catch (BrokenBarrierException success) {}
374 >                }});
375 >            Thread t2 = newStartedThread(new CheckedRunnable() {
376 >                public void realRun() throws Exception {
377 >                    awaitNumberWaiting(barrier, 1);
378 >                    long startTime = System.nanoTime();
379 >                    try {
380 >                        barrier.await(timeoutMillis(), MILLISECONDS);
381 >                        shouldThrow();
382 >                    } catch (TimeoutException success) {}
383 >                    assertTrue(millisElapsedSince(startTime) >= timeoutMillis());
384 >                }});
385 >
386 >            awaitTermination(t1);
387 >            awaitTermination(t2);
388 >            assertEquals(0, barrier.getNumberWaiting());
389 >            assertTrue(barrier.isBroken());
390 >            assertEquals(0, barrier.getNumberWaiting());
391 >            barrier.reset();
392 >            assertFalse(barrier.isBroken());
393 >            assertEquals(0, barrier.getNumberWaiting());
394 >        }
395 >    }
396 >
397 >    /**
398 >     * Reset of a barrier after a failed command reinitializes it.
399 >     */
400 >    public void testResetAfterCommandException() throws Exception {
401 >        final CyclicBarrier barrier =
402 >            new CyclicBarrier(3, new Runnable() {
403 >                    public void run() {
404 >                        throw new NullPointerException(); }});
405 >        for (int i = 0; i < 2; i++) {
406 >            final CyclicBarrier start = new CyclicBarrier(3);
407 >            Thread t1 = new ThreadShouldThrow(BrokenBarrierException.class) {
408 >                public void realRun() throws Exception {
409 >                    start.await();
410 >                    barrier.await();
411 >                }};
412 >
413 >            Thread t2 = new ThreadShouldThrow(BrokenBarrierException.class) {
414 >                public void realRun() throws Exception {
415 >                    start.await();
416 >                    barrier.await();
417 >                }};
418 >
419              t1.start();
420              t2.start();
421 <            Thread.sleep(SHORT_DELAY_MS);
422 <            t1.interrupt();
423 <            t1.join();
424 <            t2.join();
425 <        } catch(InterruptedException e){
426 <            fail("unexpected exception");
421 >            start.await();
422 >            awaitNumberWaiting(barrier, 2);
423 >            try {
424 >                barrier.await();
425 >                shouldThrow();
426 >            } catch (NullPointerException success) {}
427 >            awaitTermination(t1);
428 >            awaitTermination(t2);
429 >            assertTrue(barrier.isBroken());
430 >            assertEquals(0, barrier.getNumberWaiting());
431 >            barrier.reset();
432 >            assertFalse(barrier.isBroken());
433 >            assertEquals(0, barrier.getNumberWaiting());
434          }
435      }
436 <    
437 <    public void testAwait3_TimeOutException(){
438 <        final CyclicBarrier c = new CyclicBarrier(2);
439 <        Thread t = new Thread(new Runnable() {
440 <                public void run(){
441 <                    try{
442 <                        c.await(SHORT_DELAY_MS, TimeUnit.MILLISECONDS);
443 <                        fail("should throw");
444 <                    } catch(TimeoutException success){
445 <                    } catch(Exception b){
446 <                        fail("should throw TOE");
447 <                        
448 <                    }
449 <                }
450 <            });
451 <        try {
452 <            t.start();
453 <            t.join();
454 <        } catch(InterruptedException e){
455 <            fail("unexpected exception");
436 >
437 >    /**
438 >     * There can be more threads calling await() than parties, as long as each
439 >     * task only calls await once and the task count is a multiple of parties.
440 >     */
441 >    public void testMoreTasksThanParties() throws Exception {
442 >        final ThreadLocalRandom rnd = ThreadLocalRandom.current();
443 >        final int parties = rnd.nextInt(1, 5);
444 >        final int nTasks = rnd.nextInt(1, 5) * parties;
445 >        final AtomicInteger tripCount = new AtomicInteger(0);
446 >        final AtomicInteger awaitCount = new AtomicInteger(0);
447 >        final CyclicBarrier barrier =
448 >            new CyclicBarrier(parties, () -> tripCount.getAndIncrement());
449 >        final ExecutorService e = Executors.newFixedThreadPool(nTasks);
450 >        final Runnable awaiter = () -> {
451 >            try {
452 >                if (randomBoolean())
453 >                    barrier.await();
454 >                else
455 >                    barrier.await(LONG_DELAY_MS, MILLISECONDS);
456 >                awaitCount.getAndIncrement();
457 >            } catch (Throwable fail) { threadUnexpectedException(fail); }};
458 >        try (PoolCleaner cleaner = cleaner(e)) {
459 >            for (int i = nTasks; i--> 0; )
460 >                e.execute(awaiter);
461          }
462 +        assertEquals(nTasks / parties, tripCount.get());
463 +        assertEquals(nTasks, awaitCount.get());
464 +        assertEquals(0, barrier.getNumberWaiting());
465      }
202    
466   }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines