ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/test/tck/PhaserTest.java
Revision: 1.18
Committed: Tue Oct 12 06:19:44 2010 UTC (13 years, 6 months ago) by jsr166
Branch: MAIN
Changes since 1.17: +29 -36 lines
Log Message:
performance and reliability improvements

File Contents

# Content
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/licenses/publicdomain
5 * Other contributors include John Vint
6 */
7
8 import java.util.ArrayList;
9 import java.util.List;
10 import java.util.concurrent.atomic.AtomicInteger;
11 import java.util.concurrent.atomic.AtomicBoolean;
12 import java.util.concurrent.*;
13 import static java.util.concurrent.TimeUnit.MILLISECONDS;
14 import junit.framework.Test;
15 import junit.framework.TestSuite;
16
17 public class PhaserTest extends JSR166TestCase {
18
19 public static void main(String[] args) {
20 junit.textui.TestRunner.run(suite());
21 }
22
23 public static Test suite() {
24 return new TestSuite(PhaserTest.class);
25 }
26
27 /**
28 * Empty constructor builds a new Phaser with no parent, no registered
29 * parties and initial phase number of 0
30 */
31 public void testConstructor1() {
32 Phaser phaser = new Phaser();
33 assertNull(phaser.getParent());
34 assertEquals(0, phaser.getArrivedParties());
35 assertEquals(0, phaser.getPhase());
36 }
37
38 /**
39 * A negative party number for the constructor throws illegal argument
40 * exception
41 */
42 public void testConstructor2() {
43 try {
44 new Phaser(-1);
45 shouldThrow();
46 } catch (IllegalArgumentException success) {}
47 }
48
49 /**
50 * The parent being input into the constructor should equal the original
51 * parent when being returned
52 */
53 public void testConstructor3() {
54 Phaser parent = new Phaser();
55 assertEquals(parent, new Phaser(parent).getParent());
56 }
57
58 /**
59 * A negative party number for the constructor throws illegal argument
60 * exception
61 */
62 public void testConstructor4() {
63 try {
64 new Phaser(new Phaser(), -1);
65 shouldThrow();
66 } catch (IllegalArgumentException success) {}
67 }
68
69 /**
70 * The parent being input into the parameter should equal the original
71 * parent when being returned
72 */
73 public void testConstructor5() {
74 Phaser parent = new Phaser();
75 assertEquals(parent, new Phaser(parent, 0).getParent());
76 }
77
78 /**
79 * register() will increment the number of unarrived parties by one and not
80 * affect its arrived parties
81 */
82 public void testRegister1() {
83 Phaser phaser = new Phaser();
84 assertEquals(0, phaser.getUnarrivedParties());
85 phaser.register();
86 assertEquals(1, phaser.getUnarrivedParties());
87 assertEquals(0, phaser.getArrivedParties());
88 }
89
90 /**
91 * Registering more than 65536 parties causes IllegalStateException
92 */
93 public void testRegister2() {
94 Phaser phaser = new Phaser(0);
95 int expectedUnnarivedParties = (1 << 16) - 1;
96 for (int i = 0; i < expectedUnnarivedParties; i++) {
97 phaser.register();
98 assertEquals(i + 1, phaser.getUnarrivedParties());
99 }
100 try {
101 phaser.register();
102 shouldThrow();
103 } catch (IllegalStateException success) {}
104 }
105
106 /**
107 * register() correctly returns the current barrier phase number when
108 * invoked
109 */
110 public void testRegister3() {
111 Phaser phaser = new Phaser();
112 assertEquals(0, phaser.register());
113 phaser.arrive();
114 assertEquals(1, phaser.register());
115 }
116
117 /**
118 * register causes the next arrive to not increment the phase rather retain
119 * the phase number
120 */
121 public void testRegister4() {
122 Phaser phaser = new Phaser(1);
123 phaser.arrive();
124 int expectedPhase = phaser.register();
125 phaser.arrive();
126 assertEquals(expectedPhase, phaser.getPhase());
127 }
128
129 public void testRegister5() {
130 Phaser phaser = new Phaser();
131 phaser.register();
132 assertEquals(1, phaser.getUnarrivedParties());
133 }
134
135 /**
136 * Invoking bulkRegister with a negative parameter throws an
137 * IllegalArgumentException
138 */
139 public void testBulkRegister1() {
140 try {
141 new Phaser().bulkRegister(-1);
142 shouldThrow();
143 } catch (IllegalArgumentException success) {}
144 }
145
146 /**
147 * bulkRegister should correctly record the number of unarrived parties with
148 * the number of parties being registered
149 */
150 public void testBulkRegister2() {
151 Phaser phaser = new Phaser();
152 phaser.bulkRegister(20);
153 assertEquals(20, phaser.getUnarrivedParties());
154 }
155
156 /**
157 * Registering with a number of parties greater than or equal to 1<<16
158 * throws IllegalStateException.
159 */
160 public void testBulkRegister3() {
161 try {
162 new Phaser().bulkRegister(1 << 16);
163 shouldThrow();
164 } catch (IllegalStateException success) {}
165 }
166
167 /**
168 * the phase number increments correctly when tripping the barrier
169 */
170 public void testPhaseIncrement1() {
171 for (int size = 1; size < nine; size++) {
172 final Phaser phaser = new Phaser(size);
173 for (int index = 0; index <= (1 << size); index++) {
174 int phase = phaser.arrive();
175 assertTrue(index % size == 0 ? (index / size) == phase : index - (phase * size) > 0);
176 }
177 }
178 }
179
180 /**
181 * Arrive() on a registered phaser increments phase.
182 */
183 public void testArrive1() {
184 Phaser phaser = new Phaser(1);
185 phaser.arrive();
186 assertEquals(1, phaser.getPhase());
187 }
188
189 /**
190 * arriveAndDeregister does not wait for others to arrive at barrier
191 */
192 public void testArrive2() throws InterruptedException {
193 final Phaser phaser = new Phaser(1);
194 phaser.register();
195 List<Thread> threads = new ArrayList<Thread>();
196 for (int i = 0; i < 10; i++)
197 phaser.register();
198 threads.add(newStartedThread(new CheckedRunnable() {
199 public void realRun() throws InterruptedException {
200 Thread.sleep(SMALL_DELAY_MS);
201 phaser.arriveAndDeregister();
202 }}));
203
204 phaser.arrive();
205 assertTrue(threads.get(0).isAlive());
206 assertFalse(phaser.isTerminated());
207 for (Thread thread : threads)
208 thread.join();
209 }
210
211 /**
212 * arrive() returns a negative number if the Phaser is terminated
213 */
214 public void testArrive3() {
215 Phaser phaser = new Phaser(1);
216 phaser.forceTermination();
217 assertTrue(phaser.arrive() < 0);
218 }
219
220 /**
221 * arriveAndDeregister() throws IllegalStateException if number of
222 * registered or unarrived parties would become negative
223 */
224 public void testArriveAndDeregister1() {
225 try {
226 Phaser phaser = new Phaser();
227 phaser.arriveAndDeregister();
228 shouldThrow();
229 } catch (IllegalStateException success) {}
230 }
231
232 /**
233 * arriveAndDeregister deregisters reduces the number of arrived parties
234 */
235 public void testArriveAndDergeister2() {
236 final Phaser phaser = new Phaser(1);
237 phaser.register();
238 phaser.arrive();
239 int p = phaser.getArrivedParties();
240 assertEquals(1, p);
241 phaser.arriveAndDeregister();
242 assertTrue(phaser.getArrivedParties() < p);
243 }
244
245 /**
246 * arriveAndDeregister arrives to the barrier on a phaser with a parent and
247 * when a deregistration occurs and causes the phaser to have zero parties
248 * its parent will be deregistered as well
249 */
250 public void testArriveAndDeregsiter3() {
251 Phaser parent = new Phaser();
252 Phaser root = new Phaser(parent);
253 root.register();
254 assertTrue(parent.getUnarrivedParties() > 0);
255 assertTrue(root.getUnarrivedParties() > 0);
256 root.arriveAndDeregister();
257 assertEquals(0, parent.getUnarrivedParties());
258 assertEquals(0, root.getUnarrivedParties());
259 assertTrue(root.isTerminated() && parent.isTerminated());
260 }
261
262 /**
263 * arriveAndDeregister deregisters one party from its parent when
264 * the number of parties of root is zero after deregistration
265 */
266 public void testArriveAndDeregsiter4() {
267 Phaser parent = new Phaser();
268 Phaser root = new Phaser(parent);
269 parent.register();
270 root.register();
271 int parentParties = parent.getUnarrivedParties();
272 root.arriveAndDeregister();
273 assertEquals(parentParties - 1, parent.getUnarrivedParties());
274 }
275
276 /**
277 * arriveAndDeregister deregisters one party from its parent when
278 * the number of parties of root is nonzero after deregistration.
279 */
280 public void testArriveAndDeregister5() {
281 Phaser parent = new Phaser();
282 Phaser child = new Phaser(parent);
283 Phaser root = new Phaser(child);
284 assertTrue(parent.getUnarrivedParties() > 0);
285 assertTrue(child.getUnarrivedParties() > 0);
286 root.register();
287 root.arriveAndDeregister();
288 assertEquals(0, parent.getUnarrivedParties());
289 assertEquals(0, child.getUnarrivedParties());
290 assertTrue(root.isTerminated());
291 }
292
293 /**
294 * arriveAndDeregister returns the phase in which it leaves the
295 * phaser in after deregistration
296 */
297 public void testArriveAndDeregister6() throws InterruptedException {
298 final Phaser phaser = new Phaser(2);
299 Thread t = newStartedThread(new CheckedRunnable() {
300 public void realRun() {
301 sleepTillInterrupted(SHORT_DELAY_MS);
302 phaser.arrive();
303 }});
304 phaser.arriveAndAwaitAdvance();
305 int phase = phaser.arriveAndDeregister();
306 assertEquals(phase, phaser.getPhase());
307 t.join();
308 }
309
310 /**
311 * awaitAdvance succeeds upon advance
312 */
313 public void testAwaitAdvance1() {
314 final Phaser phaser = new Phaser(1);
315 phaser.awaitAdvance(phaser.arrive());
316 }
317
318 /**
319 * awaitAdvance with a negative parameter will return without affecting the
320 * phaser
321 */
322 public void testAwaitAdvance2() {
323 Phaser phaser = new Phaser();
324 phaser.awaitAdvance(-1);
325 }
326
327 /**
328 * awaitAdvance while waiting does not abort on interrupt.
329 */
330 public void testAwaitAdvance3() throws InterruptedException {
331 final Phaser phaser = new Phaser();
332 phaser.register();
333 final CountDownLatch threadStarted = new CountDownLatch(1);
334
335 Thread t = newStartedThread(new CheckedRunnable() {
336 public void realRun() throws InterruptedException {
337 phaser.register();
338 threadStarted.countDown();
339 phaser.awaitAdvance(phaser.arrive());
340 assertTrue(Thread.currentThread().isInterrupted());
341 }});
342 assertTrue(threadStarted.await(SMALL_DELAY_MS, MILLISECONDS));
343 t.interrupt();
344 phaser.arrive();
345 awaitTermination(t, SMALL_DELAY_MS);
346 }
347
348 /**
349 * awaitAdvance atomically waits for all parties within the same phase to
350 * complete before continuing
351 */
352 public void testAwaitAdvance4() throws InterruptedException {
353 final Phaser phaser = new Phaser(4);
354 final AtomicInteger phaseCount = new AtomicInteger(0);
355 List<Thread> threads = new ArrayList<Thread>();
356 for (int i = 0; i < 4; i++) {
357 threads.add(newStartedThread(new CheckedRunnable() {
358 public void realRun() {
359 int phase = phaser.arrive();
360 phaseCount.incrementAndGet();
361 sleepTillInterrupted(SMALL_DELAY_MS);
362 phaser.awaitAdvance(phase);
363 assertEquals(phaseCount.get(), 4);
364 }}));
365 }
366 for (Thread thread : threads)
367 thread.join();
368 }
369
370 /**
371 * awaitAdvance returns the current phase
372 */
373 public void testAwaitAdvance5() throws InterruptedException {
374 final Phaser phaser = new Phaser(1);
375 int phase = phaser.awaitAdvance(phaser.arrive());
376 assertEquals(phase, phaser.getPhase());
377 phaser.register();
378 List<Thread> threads = new ArrayList<Thread>();
379 for (int i = 0; i < 8; i++) {
380 final CountDownLatch latch = new CountDownLatch(1);
381 final boolean goesFirst = ((i & 1) == 0);
382 threads.add(newStartedThread(new CheckedRunnable() {
383 public void realRun() throws InterruptedException {
384 if (goesFirst)
385 latch.countDown();
386 else
387 assertTrue(latch.await(SMALL_DELAY_MS, MILLISECONDS));
388 phaser.arrive();
389 }}));
390 if (goesFirst)
391 assertTrue(latch.await(SMALL_DELAY_MS, MILLISECONDS));
392 else
393 latch.countDown();
394 phase = phaser.awaitAdvance(phaser.arrive());
395 assertEquals(phase, phaser.getPhase());
396 }
397 for (Thread thread : threads)
398 awaitTermination(thread, SMALL_DELAY_MS);
399 }
400
401 /**
402 * awaitAdvance returns when the phaser is externally terminated
403 */
404 public void testAwaitAdvance6() throws InterruptedException {
405 final Phaser phaser = new Phaser(3);
406 final CountDownLatch threadsStarted = new CountDownLatch(2);
407 final List<Thread> threads = new ArrayList<Thread>();
408 for (int i = 0; i < 2; i++) {
409 Runnable r = new CheckedRunnable() {
410 public void realRun() {
411 int p1 = phaser.arrive();
412 assertTrue(p1 >= 0);
413 threadsStarted.countDown();
414 int phase = phaser.awaitAdvance(p1);
415 assertTrue(phase < 0);
416 assertTrue(phaser.isTerminated());
417 }};
418 threads.add(newStartedThread(r));
419 }
420 threadsStarted.await();
421 phaser.forceTermination();
422 for (Thread thread : threads)
423 awaitTermination(thread, SMALL_DELAY_MS);
424 }
425
426 /**
427 * arriveAndAwaitAdvance throws IllegalStateException with no
428 * unarrived parties
429 */
430 public void testArriveAndAwaitAdvance1() {
431 try {
432 Phaser phaser = new Phaser();
433 phaser.arriveAndAwaitAdvance();
434 shouldThrow();
435 } catch (IllegalStateException success) {}
436 }
437
438 /**
439 * Interrupted arriveAndAwaitAdvance does not throw InterruptedException
440 */
441 public void testArriveAndAwaitAdvance2() throws InterruptedException {
442 final Phaser phaser = new Phaser(2);
443 final CountDownLatch threadStarted = new CountDownLatch(1);
444 final AtomicBoolean advanced = new AtomicBoolean(false);
445 final AtomicBoolean checkedInterruptStatus = new AtomicBoolean(false);
446 Thread t = newStartedThread(new CheckedRunnable() {
447 public void realRun() throws InterruptedException {
448 threadStarted.countDown();
449 phaser.arriveAndAwaitAdvance();
450 advanced.set(true);
451 assertTrue(Thread.currentThread().isInterrupted());
452 while (!checkedInterruptStatus.get())
453 Thread.yield();
454 }});
455
456 assertTrue(threadStarted.await(SMALL_DELAY_MS, MILLISECONDS));
457 t.interrupt();
458 phaser.arrive();
459 while (!advanced.get())
460 Thread.yield();
461 assertTrue(t.isInterrupted());
462 checkedInterruptStatus.set(true);
463 awaitTermination(t, SMALL_DELAY_MS);
464 }
465
466 /**
467 * arriveAndAwaitAdvance waits for all threads to arrive, the
468 * number of arrived parties is the same number that is accounted
469 * for when the main thread awaitsAdvance
470 */
471 public void testArriveAndAwaitAdvance3() throws InterruptedException {
472 final Phaser phaser = new Phaser(1);
473 final List<Thread> threads = new ArrayList<Thread>();
474 for (int i = 0; i < 3; i++) {
475 threads.add(newStartedThread(new CheckedRunnable() {
476 public void realRun() throws InterruptedException {
477 phaser.register();
478 phaser.arriveAndAwaitAdvance();
479 }}));
480 }
481 Thread.sleep(MEDIUM_DELAY_MS);
482 assertEquals(phaser.getArrivedParties(), 3);
483 phaser.arriveAndAwaitAdvance();
484 for (Thread thread : threads)
485 thread.join();
486 }
487
488 }