6 |
|
* Pat Fisher, Mike Judd. |
7 |
|
*/ |
8 |
|
|
9 |
< |
import junit.framework.*; |
10 |
< |
import java.util.*; |
9 |
> |
import static java.util.concurrent.TimeUnit.MILLISECONDS; |
10 |
> |
|
11 |
> |
import java.util.Collection; |
12 |
|
import java.util.concurrent.CountDownLatch; |
13 |
|
import java.util.concurrent.Semaphore; |
14 |
< |
import static java.util.concurrent.TimeUnit.MILLISECONDS; |
14 |
> |
|
15 |
> |
import junit.framework.AssertionFailedError; |
16 |
> |
import junit.framework.Test; |
17 |
> |
import junit.framework.TestSuite; |
18 |
|
|
19 |
|
public class SemaphoreTest extends JSR166TestCase { |
20 |
|
public static void main(String[] args) { |
21 |
< |
junit.textui.TestRunner.run(suite()); |
21 |
> |
main(suite(), args); |
22 |
|
} |
23 |
|
public static Test suite() { |
24 |
|
return new TestSuite(SemaphoreTest.class); |
76 |
|
throw new AssertionFailedError("timed out"); |
77 |
|
Thread.yield(); |
78 |
|
} |
79 |
< |
assert(s.hasQueuedThreads()); |
79 |
> |
assertTrue(s.hasQueuedThreads()); |
80 |
|
assertTrue(t.isAlive()); |
81 |
|
} |
82 |
|
|
227 |
|
public void testInterruptible_tryAcquireTimedN_fair() { testInterruptible(true, AcquireMethod.tryAcquireTimedN); } |
228 |
|
public void testInterruptible(boolean fair, final AcquireMethod acquirer) { |
229 |
|
final PublicSemaphore s = new PublicSemaphore(0, fair); |
230 |
< |
final Semaphore anotherInterruptPlease = new Semaphore(0, fair); |
230 |
> |
final Semaphore pleaseInterrupt = new Semaphore(0, fair); |
231 |
|
Thread t = newStartedThread(new CheckedRunnable() { |
232 |
|
public void realRun() { |
233 |
|
// Interrupt before acquire |
250 |
|
shouldThrow(); |
251 |
|
} catch (InterruptedException success) {} |
252 |
|
|
253 |
< |
anotherInterruptPlease.release(); |
253 |
> |
pleaseInterrupt.release(); |
254 |
|
|
255 |
|
// Interrupt during acquire(N) |
256 |
|
try { |
261 |
|
|
262 |
|
waitForQueuedThread(s, t); |
263 |
|
t.interrupt(); |
264 |
< |
try { |
261 |
< |
assertTrue(anotherInterruptPlease.tryAcquire(LONG_DELAY_MS, MILLISECONDS)); |
262 |
< |
} catch (InterruptedException e) { threadUnexpectedException(e); } |
264 |
> |
await(pleaseInterrupt); |
265 |
|
waitForQueuedThread(s, t); |
266 |
|
t.interrupt(); |
267 |
|
awaitTermination(t); |
277 |
|
public void testUninterruptible_acquireUninterruptiblyN_fair() { testUninterruptible(true, AcquireMethod.acquireUninterruptiblyN); } |
278 |
|
public void testUninterruptible(boolean fair, final AcquireMethod acquirer) { |
279 |
|
final PublicSemaphore s = new PublicSemaphore(0, fair); |
280 |
< |
final Semaphore anotherInterruptPlease = new Semaphore(0, fair); |
281 |
< |
Thread t = newStartedThread(new CheckedRunnable() { |
280 |
> |
final Semaphore pleaseInterrupt = new Semaphore(-1, fair); |
281 |
> |
|
282 |
> |
Thread t1 = newStartedThread(new CheckedRunnable() { |
283 |
|
public void realRun() throws InterruptedException { |
284 |
|
// Interrupt before acquire |
285 |
+ |
pleaseInterrupt.release(); |
286 |
|
Thread.currentThread().interrupt(); |
287 |
|
acquirer.acquire(s); |
288 |
|
assertTrue(Thread.interrupted()); |
289 |
+ |
}}); |
290 |
|
|
291 |
< |
anotherInterruptPlease.release(); |
292 |
< |
|
291 |
> |
Thread t2 = newStartedThread(new CheckedRunnable() { |
292 |
> |
public void realRun() throws InterruptedException { |
293 |
|
// Interrupt during acquire |
294 |
+ |
pleaseInterrupt.release(); |
295 |
|
acquirer.acquire(s); |
296 |
|
assertTrue(Thread.interrupted()); |
297 |
|
}}); |
298 |
|
|
299 |
< |
waitForQueuedThread(s, t); |
300 |
< |
assertThreadStaysAlive(t); |
301 |
< |
s.release(); |
299 |
> |
await(pleaseInterrupt); |
300 |
> |
waitForQueuedThread(s, t1); |
301 |
> |
waitForQueuedThread(s, t2); |
302 |
> |
t2.interrupt(); |
303 |
|
|
304 |
< |
try { |
305 |
< |
assertTrue(anotherInterruptPlease.tryAcquire(LONG_DELAY_MS, MILLISECONDS)); |
299 |
< |
} catch (InterruptedException e) { threadUnexpectedException(e); } |
300 |
< |
waitForQueuedThread(s, t); |
301 |
< |
t.interrupt(); |
302 |
< |
assertThreadStaysAlive(t); |
303 |
< |
s.release(); |
304 |
> |
assertThreadStaysAlive(t1); |
305 |
> |
assertTrue(t2.isAlive()); |
306 |
|
|
307 |
< |
awaitTermination(t); |
307 |
> |
s.release(2); |
308 |
> |
|
309 |
> |
awaitTermination(t1); |
310 |
> |
awaitTermination(t2); |
311 |
|
} |
312 |
|
|
313 |
|
/** |
467 |
|
clone.release(); |
468 |
|
assertEquals(2, s.availablePermits()); |
469 |
|
assertEquals(1, clone.availablePermits()); |
470 |
+ |
assertFalse(s.hasQueuedThreads()); |
471 |
+ |
assertFalse(clone.hasQueuedThreads()); |
472 |
+ |
} catch (InterruptedException e) { threadUnexpectedException(e); } |
473 |
|
|
474 |
< |
s = new Semaphore(0, fair); |
474 |
> |
{ |
475 |
> |
PublicSemaphore s = new PublicSemaphore(0, fair); |
476 |
|
Thread t = newStartedThread(new InterruptibleLockRunnable(s)); |
477 |
< |
waitForQueuedThreads(s); |
478 |
< |
clone = serialClone(s); |
477 |
> |
// waitForQueuedThreads(s); // suffers from "flicker", so ... |
478 |
> |
waitForQueuedThread(s, t); // ... we use this instead |
479 |
> |
PublicSemaphore clone = serialClone(s); |
480 |
|
assertEquals(fair, s.isFair()); |
481 |
|
assertEquals(fair, clone.isFair()); |
482 |
|
assertEquals(0, s.availablePermits()); |
487 |
|
awaitTermination(t); |
488 |
|
assertFalse(s.hasQueuedThreads()); |
489 |
|
assertFalse(clone.hasQueuedThreads()); |
490 |
< |
} catch (InterruptedException e) { threadUnexpectedException(e); } |
490 |
> |
} |
491 |
|
} |
492 |
|
|
493 |
|
/** |
595 |
|
s.acquire(3); |
596 |
|
}}); |
597 |
|
|
598 |
< |
waitForQueuedThreads(s); |
598 |
> |
waitForQueuedThread(s, t1); |
599 |
|
|
600 |
|
Thread t2 = newStartedThread(new CheckedRunnable() { |
601 |
|
public void realRun() throws InterruptedException { |
621 |
|
assertTrue(t2.isAlive()); |
622 |
|
s.release(); |
623 |
|
awaitTermination(t2); |
624 |
< |
} |
624 |
> |
} |
625 |
|
|
626 |
|
/** |
627 |
|
* toString indicates current number of permits |