35 import java.util.Iterator; |
35 import java.util.Iterator; |
36 import java.util.List; |
36 import java.util.List; |
37 import java.util.concurrent.BrokenBarrierException; |
37 import java.util.concurrent.BrokenBarrierException; |
38 import java.util.concurrent.CountDownLatch; |
38 import java.util.concurrent.CountDownLatch; |
39 import java.util.concurrent.CyclicBarrier; |
39 import java.util.concurrent.CyclicBarrier; |
|
40 import java.util.concurrent.ThreadLocalRandom; |
40 import java.util.concurrent.TimeoutException; |
41 import java.util.concurrent.TimeoutException; |
41 import java.util.concurrent.atomic.AtomicInteger; |
42 import java.util.concurrent.atomic.AtomicInteger; |
42 import jdk.test.lib.Utils; |
43 import jdk.test.lib.Utils; |
43 |
44 |
44 public class Basic { |
45 public class Basic { |
291 |
292 |
292 /** |
293 /** |
293 * Handling of extra interrupts while waiting - tests for bug 6366811 |
294 * Handling of extra interrupts while waiting - tests for bug 6366811 |
294 */ |
295 */ |
295 private static void testInterrupts() { |
296 private static void testInterrupts() { |
296 final int N = 10; |
297 final int N = ThreadLocalRandom.current().nextInt(2, 10); |
297 final CyclicBarrier startingGate = new CyclicBarrier(N+1); |
298 final CyclicBarrier startingGate = new CyclicBarrier(N+1); |
298 |
299 |
299 /** |
300 /** |
300 * A version of Awaiter that also records interrupted state. |
301 * A version of Awaiter that also records interrupted state. |
301 */ |
302 */ |
302 class Waiter extends CheckedThread { |
303 class Waiter extends CheckedThread { |
303 private boolean timed; |
304 private final boolean timed; |
304 private CyclicBarrier barrier; |
305 private final CyclicBarrier barrier; |
305 private CountDownLatch doneSignal; |
306 private final CountDownLatch doneSignal; |
306 private Throwable throwable; |
307 volatile Throwable throwable; |
307 private boolean interrupted; |
308 volatile boolean interruptStatusSetAfterAwait; |
308 |
309 |
309 public Waiter(boolean timed, |
310 public Waiter(CountDownLatch doneSignal, CyclicBarrier barrier) { |
310 CountDownLatch doneSignal, |
311 this.timed = ThreadLocalRandom.current().nextBoolean(); |
311 CyclicBarrier barrier) { |
|
312 this.timed = timed; |
|
313 this.doneSignal = doneSignal; |
312 this.doneSignal = doneSignal; |
314 this.barrier = barrier; |
313 this.barrier = barrier; |
315 } |
314 } |
316 Throwable throwable() { return this.throwable; } |
315 |
317 boolean interruptBit() { return this.interrupted; } |
|
318 void realRun() throws Throwable { |
316 void realRun() throws Throwable { |
319 startingGate.await(LONG_DELAY_MS, MILLISECONDS); |
317 startingGate.await(LONG_DELAY_MS, MILLISECONDS); |
|
318 |
320 try { |
319 try { |
321 if (timed) barrier.await(LONG_DELAY_MS, MILLISECONDS); |
320 if (timed) barrier.await(LONG_DELAY_MS, MILLISECONDS); |
322 else barrier.await(); } |
321 else barrier.await(); |
323 catch (Throwable throwable) { this.throwable = throwable; } |
322 } catch (Throwable throwable) { |
324 |
323 this.throwable = throwable; |
325 try { doneSignal.await(LONG_DELAY_MS, MILLISECONDS); } |
324 } |
326 catch (InterruptedException e) { interrupted = true; } |
325 |
|
326 try { |
|
327 check(doneSignal.await(LONG_DELAY_MS, MILLISECONDS)); |
|
328 if (Thread.interrupted()) |
|
329 interruptStatusSetAfterAwait = true; |
|
330 } catch (InterruptedException e) { |
|
331 interruptStatusSetAfterAwait = true; |
|
332 } |
327 } |
333 } |
328 } |
334 } |
329 |
335 |
330 //---------------------------------------------------------------- |
336 //---------------------------------------------------------------- |
331 // Interrupt occurs during barrier trip |
337 // Interrupt occurs during barrier trip |
350 // seems to work reliably while yield does not. |
356 // seems to work reliably while yield does not. |
351 Thread.sleep(100); |
357 Thread.sleep(100); |
352 } catch (Throwable t) { unexpected(t); } |
358 } catch (Throwable t) { unexpected(t); } |
353 }}; |
359 }}; |
354 for (int i = 0; i < N; i++) { |
360 for (int i = 0; i < N; i++) { |
355 Waiter waiter = new Waiter(i < N/2, doneSignal, barrier); |
361 Waiter waiter = new Waiter(doneSignal, barrier); |
356 waiter.start(); |
362 waiter.start(); |
357 waiters.add(waiter); |
363 waiters.add(waiter); |
358 } |
364 } |
359 startingGate.await(LONG_DELAY_MS, MILLISECONDS); |
365 startingGate.await(LONG_DELAY_MS, MILLISECONDS); |
360 while (barrier.getNumberWaiting() < N) Thread.yield(); |
366 while (barrier.getNumberWaiting() < N) Thread.yield(); |
361 barrier.await(); |
367 barrier.await(); |
362 doneSignal.countDown(); |
368 doneSignal.countDown(); |
363 int countInterrupted = 0; |
369 int countInterruptStatusSetAfterAwait = 0; |
364 int countInterruptedException = 0; |
|
365 int countBrokenBarrierException = 0; |
|
366 for (Waiter waiter : waiters) { |
370 for (Waiter waiter : waiters) { |
367 waiter.join(); |
371 waiter.join(); |
368 equal(waiter.throwable(), null); |
372 equal(waiter.throwable, null); |
369 if (waiter.interruptBit()) |
373 if (waiter.interruptStatusSetAfterAwait) |
370 countInterrupted++; |
374 countInterruptStatusSetAfterAwait++; |
371 } |
375 } |
372 equal(countInterrupted, N/2); |
376 equal(countInterruptStatusSetAfterAwait, N/2); |
373 check(! barrier.isBroken()); |
377 check(! barrier.isBroken()); |
374 } catch (Throwable t) { unexpected(t); } |
378 } catch (Throwable t) { unexpected(t); } |
375 |
379 |
376 //---------------------------------------------------------------- |
380 //---------------------------------------------------------------- |
377 // Multiple interrupts occur during barrier await |
381 // Multiple interrupts occur during barrier await |
379 try { |
383 try { |
380 final CountDownLatch doneSignal = new CountDownLatch(1); |
384 final CountDownLatch doneSignal = new CountDownLatch(1); |
381 final CyclicBarrier barrier = new CyclicBarrier(N+1); |
385 final CyclicBarrier barrier = new CyclicBarrier(N+1); |
382 final List<Waiter> waiters = new ArrayList<>(N); |
386 final List<Waiter> waiters = new ArrayList<>(N); |
383 for (int i = 0; i < N; i++) { |
387 for (int i = 0; i < N; i++) { |
384 Waiter waiter = new Waiter(i < N/2, doneSignal, barrier); |
388 Waiter waiter = new Waiter(doneSignal, barrier); |
385 waiter.start(); |
389 waiter.start(); |
386 waiters.add(waiter); |
390 waiters.add(waiter); |
387 } |
391 } |
388 startingGate.await(LONG_DELAY_MS, MILLISECONDS); |
392 startingGate.await(LONG_DELAY_MS, MILLISECONDS); |
389 while (barrier.getNumberWaiting() < N) Thread.yield(); |
393 while (barrier.getNumberWaiting() < N) Thread.yield(); |
390 for (int i = 0; i < N/2; i++) |
394 for (int i = 0; i < N/2; i++) { |
391 waiters.get(i).interrupt(); |
395 Thread waiter = waiters.get(i); |
|
396 waiter.interrupt(); |
|
397 } |
392 doneSignal.countDown(); |
398 doneSignal.countDown(); |
393 int countInterrupted = 0; |
|
394 int countInterruptedException = 0; |
399 int countInterruptedException = 0; |
395 int countBrokenBarrierException = 0; |
400 int countBrokenBarrierException = 0; |
|
401 int countInterruptStatusSetAfterAwait = 0; |
396 for (Waiter waiter : waiters) { |
402 for (Waiter waiter : waiters) { |
397 waiter.join(); |
403 waiter.join(); |
398 if (waiter.throwable() instanceof InterruptedException) |
404 if (waiter.throwable instanceof InterruptedException) |
399 countInterruptedException++; |
405 countInterruptedException++; |
400 if (waiter.throwable() instanceof BrokenBarrierException) |
406 if (waiter.throwable instanceof BrokenBarrierException) |
401 countBrokenBarrierException++; |
407 countBrokenBarrierException++; |
402 if (waiter.interruptBit()) |
408 if (waiter.interruptStatusSetAfterAwait) |
403 countInterrupted++; |
409 countInterruptStatusSetAfterAwait++; |
404 } |
410 } |
405 equal(countInterrupted, N/2-1); |
|
406 equal(countInterruptedException, 1); |
411 equal(countInterruptedException, 1); |
407 equal(countBrokenBarrierException, N-1); |
412 equal(countBrokenBarrierException, N-1); |
408 checkBroken(barrier); |
413 checkBroken(barrier); |
|
414 equal(countInterruptStatusSetAfterAwait, N/2-1); |
409 reset(barrier); |
415 reset(barrier); |
410 } catch (Throwable t) { unexpected(t); } |
416 } catch (Throwable t) { unexpected(t); } |
411 } |
417 } |
412 |
418 |
413 //--------------------- Infrastructure --------------------------- |
419 //--------------------- Infrastructure --------------------------- |