1/* 2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 3 * 4 * This code is free software; you can redistribute it and/or modify it 5 * under the terms of the GNU General Public License version 2 only, as 6 * published by the Free Software Foundation. 7 * 8 * This code is distributed in the hope that it will be useful, but WITHOUT 9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 11 * version 2 for more details (a copy is included in the LICENSE file that 12 * accompanied this code). 13 * 14 * You should have received a copy of the GNU General Public License version 15 * 2 along with this work; if not, write to the Free Software Foundation, 16 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 17 * 18 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 19 * or visit www.oracle.com if you need additional information or have any 20 * questions. 21 */ 22 23/* 24 * This file is available under and governed by the GNU General Public 25 * License version 2 only, as published by the Free Software Foundation. 26 * However, the following notice accompanied the original version of this 27 * file: 28 * 29 * Written by Doug Lea with assistance from members of JCP JSR-166 30 * Expert Group and released to the public domain, as explained at 31 * http://creativecommons.org/publicdomain/zero/1.0/ 32 * Other contributors include Andrew Wright, Jeffrey Hayes, 33 * Pat Fisher, Mike Judd. 34 */ 35 36import static java.util.concurrent.TimeUnit.MILLISECONDS; 37 38import java.util.concurrent.BrokenBarrierException; 39import java.util.concurrent.CountDownLatch; 40import java.util.concurrent.CyclicBarrier; 41import java.util.concurrent.TimeoutException; 42import java.util.concurrent.atomic.AtomicBoolean; 43import java.util.concurrent.atomic.AtomicInteger; 44 45import junit.framework.Test; 46import junit.framework.TestSuite; 47 48public class CyclicBarrierTest extends JSR166TestCase { 49 public static void main(String[] args) { 50 main(suite(), args); 51 } 52 public static Test suite() { 53 return new TestSuite(CyclicBarrierTest.class); 54 } 55 56 /** 57 * Spin-waits till the number of waiters == numberOfWaiters. 58 */ 59 void awaitNumberWaiting(CyclicBarrier barrier, int numberOfWaiters) { 60 long startTime = System.nanoTime(); 61 while (barrier.getNumberWaiting() != numberOfWaiters) { 62 if (millisElapsedSince(startTime) > LONG_DELAY_MS) 63 fail("timed out"); 64 Thread.yield(); 65 } 66 } 67 68 /** 69 * Creating with negative parties throws IAE 70 */ 71 public void testConstructor1() { 72 try { 73 new CyclicBarrier(-1, (Runnable)null); 74 shouldThrow(); 75 } catch (IllegalArgumentException success) {} 76 } 77 78 /** 79 * Creating with negative parties and no action throws IAE 80 */ 81 public void testConstructor2() { 82 try { 83 new CyclicBarrier(-1); 84 shouldThrow(); 85 } catch (IllegalArgumentException success) {} 86 } 87 88 /** 89 * getParties returns the number of parties given in constructor 90 */ 91 public void testGetParties() { 92 CyclicBarrier b = new CyclicBarrier(2); 93 assertEquals(2, b.getParties()); 94 assertEquals(0, b.getNumberWaiting()); 95 } 96 97 /** 98 * A 1-party barrier triggers after single await 99 */ 100 public void testSingleParty() throws Exception { 101 CyclicBarrier b = new CyclicBarrier(1); 102 assertEquals(1, b.getParties()); 103 assertEquals(0, b.getNumberWaiting()); 104 b.await(); 105 b.await(); 106 assertEquals(0, b.getNumberWaiting()); 107 } 108 109 /** 110 * The supplied barrier action is run at barrier 111 */ 112 public void testBarrierAction() throws Exception { 113 final AtomicInteger count = new AtomicInteger(0); 114 final Runnable incCount = new Runnable() { public void run() { 115 count.getAndIncrement(); }}; 116 CyclicBarrier b = new CyclicBarrier(1, incCount); 117 assertEquals(1, b.getParties()); 118 assertEquals(0, b.getNumberWaiting()); 119 b.await(); 120 b.await(); 121 assertEquals(0, b.getNumberWaiting()); 122 assertEquals(2, count.get()); 123 } 124 125 /** 126 * A 2-party/thread barrier triggers after both threads invoke await 127 */ 128 public void testTwoParties() throws Exception { 129 final CyclicBarrier b = new CyclicBarrier(2); 130 Thread t = newStartedThread(new CheckedRunnable() { 131 public void realRun() throws Exception { 132 b.await(); 133 b.await(); 134 b.await(); 135 b.await(); 136 }}); 137 138 b.await(); 139 b.await(); 140 b.await(); 141 b.await(); 142 awaitTermination(t); 143 } 144 145 /** 146 * An interruption in one party causes others waiting in await to 147 * throw BrokenBarrierException 148 */ 149 public void testAwait1_Interrupted_BrokenBarrier() { 150 final CyclicBarrier c = new CyclicBarrier(3); 151 final CountDownLatch pleaseInterrupt = new CountDownLatch(2); 152 Thread t1 = new ThreadShouldThrow(InterruptedException.class) { 153 public void realRun() throws Exception { 154 pleaseInterrupt.countDown(); 155 c.await(); 156 }}; 157 Thread t2 = new ThreadShouldThrow(BrokenBarrierException.class) { 158 public void realRun() throws Exception { 159 pleaseInterrupt.countDown(); 160 c.await(); 161 }}; 162 163 t1.start(); 164 t2.start(); 165 await(pleaseInterrupt); 166 t1.interrupt(); 167 awaitTermination(t1); 168 awaitTermination(t2); 169 } 170 171 /** 172 * An interruption in one party causes others waiting in timed await to 173 * throw BrokenBarrierException 174 */ 175 public void testAwait2_Interrupted_BrokenBarrier() throws Exception { 176 final CyclicBarrier c = new CyclicBarrier(3); 177 final CountDownLatch pleaseInterrupt = new CountDownLatch(2); 178 Thread t1 = new ThreadShouldThrow(InterruptedException.class) { 179 public void realRun() throws Exception { 180 pleaseInterrupt.countDown(); 181 c.await(LONG_DELAY_MS, MILLISECONDS); 182 }}; 183 Thread t2 = new ThreadShouldThrow(BrokenBarrierException.class) { 184 public void realRun() throws Exception { 185 pleaseInterrupt.countDown(); 186 c.await(LONG_DELAY_MS, MILLISECONDS); 187 }}; 188 189 t1.start(); 190 t2.start(); 191 await(pleaseInterrupt); 192 t1.interrupt(); 193 awaitTermination(t1); 194 awaitTermination(t2); 195 } 196 197 /** 198 * A timeout in timed await throws TimeoutException 199 */ 200 public void testAwait3_TimeoutException() throws InterruptedException { 201 final CyclicBarrier c = new CyclicBarrier(2); 202 Thread t = newStartedThread(new CheckedRunnable() { 203 public void realRun() throws Exception { 204 long startTime = System.nanoTime(); 205 try { 206 c.await(timeoutMillis(), MILLISECONDS); 207 shouldThrow(); 208 } catch (TimeoutException success) {} 209 assertTrue(millisElapsedSince(startTime) >= timeoutMillis()); 210 }}); 211 212 awaitTermination(t); 213 } 214 215 /** 216 * A timeout in one party causes others waiting in timed await to 217 * throw BrokenBarrierException 218 */ 219 public void testAwait4_Timeout_BrokenBarrier() throws InterruptedException { 220 final CyclicBarrier c = new CyclicBarrier(3); 221 Thread t1 = newStartedThread(new CheckedRunnable() { 222 public void realRun() throws Exception { 223 try { 224 c.await(LONG_DELAY_MS, MILLISECONDS); 225 shouldThrow(); 226 } catch (BrokenBarrierException success) {} 227 }}); 228 Thread t2 = newStartedThread(new CheckedRunnable() { 229 public void realRun() throws Exception { 230 awaitNumberWaiting(c, 1); 231 long startTime = System.nanoTime(); 232 try { 233 c.await(timeoutMillis(), MILLISECONDS); 234 shouldThrow(); 235 } catch (TimeoutException success) {} 236 assertTrue(millisElapsedSince(startTime) >= timeoutMillis()); 237 }}); 238 239 awaitTermination(t1); 240 awaitTermination(t2); 241 } 242 243 /** 244 * A timeout in one party causes others waiting in await to 245 * throw BrokenBarrierException 246 */ 247 public void testAwait5_Timeout_BrokenBarrier() throws InterruptedException { 248 final CyclicBarrier c = new CyclicBarrier(3); 249 Thread t1 = newStartedThread(new CheckedRunnable() { 250 public void realRun() throws Exception { 251 try { 252 c.await(); 253 shouldThrow(); 254 } catch (BrokenBarrierException success) {} 255 }}); 256 Thread t2 = newStartedThread(new CheckedRunnable() { 257 public void realRun() throws Exception { 258 awaitNumberWaiting(c, 1); 259 long startTime = System.nanoTime(); 260 try { 261 c.await(timeoutMillis(), MILLISECONDS); 262 shouldThrow(); 263 } catch (TimeoutException success) {} 264 assertTrue(millisElapsedSince(startTime) >= timeoutMillis()); 265 }}); 266 267 awaitTermination(t1); 268 awaitTermination(t2); 269 } 270 271 /** 272 * A reset of an active barrier causes waiting threads to throw 273 * BrokenBarrierException 274 */ 275 public void testReset_BrokenBarrier() throws InterruptedException { 276 final CyclicBarrier c = new CyclicBarrier(3); 277 final CountDownLatch pleaseReset = new CountDownLatch(2); 278 Thread t1 = new ThreadShouldThrow(BrokenBarrierException.class) { 279 public void realRun() throws Exception { 280 pleaseReset.countDown(); 281 c.await(); 282 }}; 283 Thread t2 = new ThreadShouldThrow(BrokenBarrierException.class) { 284 public void realRun() throws Exception { 285 pleaseReset.countDown(); 286 c.await(); 287 }}; 288 289 t1.start(); 290 t2.start(); 291 await(pleaseReset); 292 293 awaitNumberWaiting(c, 2); 294 c.reset(); 295 awaitTermination(t1); 296 awaitTermination(t2); 297 } 298 299 /** 300 * A reset before threads enter barrier does not throw 301 * BrokenBarrierException 302 */ 303 public void testReset_NoBrokenBarrier() throws Exception { 304 final CyclicBarrier c = new CyclicBarrier(3); 305 c.reset(); 306 307 Thread t1 = newStartedThread(new CheckedRunnable() { 308 public void realRun() throws Exception { 309 c.await(); 310 }}); 311 Thread t2 = newStartedThread(new CheckedRunnable() { 312 public void realRun() throws Exception { 313 c.await(); 314 }}); 315 316 c.await(); 317 awaitTermination(t1); 318 awaitTermination(t2); 319 } 320 321 /** 322 * All threads block while a barrier is broken. 323 */ 324 public void testReset_Leakage() throws InterruptedException { 325 final CyclicBarrier c = new CyclicBarrier(2); 326 final AtomicBoolean done = new AtomicBoolean(); 327 Thread t = newStartedThread(new CheckedRunnable() { 328 public void realRun() { 329 while (!done.get()) { 330 try { 331 while (c.isBroken()) 332 c.reset(); 333 334 c.await(); 335 shouldThrow(); 336 } 337 catch (BrokenBarrierException ok) {} 338 catch (InterruptedException ok) {} 339 }}}); 340 341 for (int i = 0; i < 4; i++) { 342 delay(timeoutMillis()); 343 t.interrupt(); 344 } 345 done.set(true); 346 t.interrupt(); 347 awaitTermination(t); 348 } 349 350 /** 351 * Reset of a non-broken barrier does not break barrier 352 */ 353 public void testResetWithoutBreakage() throws Exception { 354 final CyclicBarrier barrier = new CyclicBarrier(3); 355 for (int i = 0; i < 3; i++) { 356 final CyclicBarrier start = new CyclicBarrier(3); 357 Thread t1 = newStartedThread(new CheckedRunnable() { 358 public void realRun() throws Exception { 359 start.await(); 360 barrier.await(); 361 }}); 362 363 Thread t2 = newStartedThread(new CheckedRunnable() { 364 public void realRun() throws Exception { 365 start.await(); 366 barrier.await(); 367 }}); 368 369 start.await(); 370 barrier.await(); 371 awaitTermination(t1); 372 awaitTermination(t2); 373 assertFalse(barrier.isBroken()); 374 assertEquals(0, barrier.getNumberWaiting()); 375 if (i == 1) barrier.reset(); 376 assertFalse(barrier.isBroken()); 377 assertEquals(0, barrier.getNumberWaiting()); 378 } 379 } 380 381 /** 382 * Reset of a barrier after interruption reinitializes it. 383 */ 384 public void testResetAfterInterrupt() throws Exception { 385 final CyclicBarrier barrier = new CyclicBarrier(3); 386 for (int i = 0; i < 2; i++) { 387 final CyclicBarrier start = new CyclicBarrier(3); 388 Thread t1 = new ThreadShouldThrow(InterruptedException.class) { 389 public void realRun() throws Exception { 390 start.await(); 391 barrier.await(); 392 }}; 393 394 Thread t2 = new ThreadShouldThrow(BrokenBarrierException.class) { 395 public void realRun() throws Exception { 396 start.await(); 397 barrier.await(); 398 }}; 399 400 t1.start(); 401 t2.start(); 402 start.await(); 403 t1.interrupt(); 404 awaitTermination(t1); 405 awaitTermination(t2); 406 assertTrue(barrier.isBroken()); 407 assertEquals(0, barrier.getNumberWaiting()); 408 barrier.reset(); 409 assertFalse(barrier.isBroken()); 410 assertEquals(0, barrier.getNumberWaiting()); 411 } 412 } 413 414 /** 415 * Reset of a barrier after timeout reinitializes it. 416 */ 417 public void testResetAfterTimeout() throws Exception { 418 final CyclicBarrier barrier = new CyclicBarrier(3); 419 for (int i = 0; i < 2; i++) { 420 assertEquals(0, barrier.getNumberWaiting()); 421 Thread t1 = newStartedThread(new CheckedRunnable() { 422 public void realRun() throws Exception { 423 try { 424 barrier.await(); 425 shouldThrow(); 426 } catch (BrokenBarrierException success) {} 427 }}); 428 Thread t2 = newStartedThread(new CheckedRunnable() { 429 public void realRun() throws Exception { 430 awaitNumberWaiting(barrier, 1); 431 long startTime = System.nanoTime(); 432 try { 433 barrier.await(timeoutMillis(), MILLISECONDS); 434 shouldThrow(); 435 } catch (TimeoutException success) {} 436 assertTrue(millisElapsedSince(startTime) >= timeoutMillis()); 437 }}); 438 439 awaitTermination(t1); 440 awaitTermination(t2); 441 assertEquals(0, barrier.getNumberWaiting()); 442 assertTrue(barrier.isBroken()); 443 assertEquals(0, barrier.getNumberWaiting()); 444 barrier.reset(); 445 assertFalse(barrier.isBroken()); 446 assertEquals(0, barrier.getNumberWaiting()); 447 } 448 } 449 450 /** 451 * Reset of a barrier after a failed command reinitializes it. 452 */ 453 public void testResetAfterCommandException() throws Exception { 454 final CyclicBarrier barrier = 455 new CyclicBarrier(3, new Runnable() { 456 public void run() { 457 throw new NullPointerException(); }}); 458 for (int i = 0; i < 2; i++) { 459 final CyclicBarrier start = new CyclicBarrier(3); 460 Thread t1 = new ThreadShouldThrow(BrokenBarrierException.class) { 461 public void realRun() throws Exception { 462 start.await(); 463 barrier.await(); 464 }}; 465 466 Thread t2 = new ThreadShouldThrow(BrokenBarrierException.class) { 467 public void realRun() throws Exception { 468 start.await(); 469 barrier.await(); 470 }}; 471 472 t1.start(); 473 t2.start(); 474 start.await(); 475 awaitNumberWaiting(barrier, 2); 476 try { 477 barrier.await(); 478 shouldThrow(); 479 } catch (NullPointerException success) {} 480 awaitTermination(t1); 481 awaitTermination(t2); 482 assertTrue(barrier.isBroken()); 483 assertEquals(0, barrier.getNumberWaiting()); 484 barrier.reset(); 485 assertFalse(barrier.isBroken()); 486 assertEquals(0, barrier.getNumberWaiting()); 487 } 488 } 489} 490