ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/test/tck/SemaphoreTest.java
Revision: 1.38
Committed: Sun May 14 00:38:16 2017 UTC (7 years ago) by jsr166
Branch: MAIN
Changes since 1.37: +22 -13 lines
Log Message:
improve testInterruptible

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/publicdomain/zero/1.0/
5 * Other contributors include Andrew Wright, Jeffrey Hayes,
6 * Pat Fisher, Mike Judd.
7 */
8
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
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 main(suite(), args);
22 }
23 public static Test suite() {
24 return new TestSuite(SemaphoreTest.class);
25 }
26
27 /**
28 * Subclass to expose protected methods
29 */
30 static class PublicSemaphore extends Semaphore {
31 PublicSemaphore(int permits) { super(permits); }
32 PublicSemaphore(int permits, boolean fair) { super(permits, fair); }
33 public Collection<Thread> getQueuedThreads() {
34 return super.getQueuedThreads();
35 }
36 public boolean hasQueuedThread(Thread t) {
37 return super.getQueuedThreads().contains(t);
38 }
39 public void reducePermits(int reduction) {
40 super.reducePermits(reduction);
41 }
42 }
43
44 /**
45 * A runnable calling acquire
46 */
47 class InterruptibleLockRunnable extends CheckedRunnable {
48 final Semaphore lock;
49 InterruptibleLockRunnable(Semaphore s) { lock = s; }
50 public void realRun() {
51 try {
52 lock.acquire();
53 }
54 catch (InterruptedException ignored) {}
55 }
56 }
57
58 /**
59 * A runnable calling acquire that expects to be interrupted
60 */
61 class InterruptedLockRunnable extends CheckedInterruptedRunnable {
62 final Semaphore lock;
63 InterruptedLockRunnable(Semaphore s) { lock = s; }
64 public void realRun() throws InterruptedException {
65 lock.acquire();
66 }
67 }
68
69 /**
70 * Spin-waits until s.hasQueuedThread(t) becomes true.
71 */
72 void waitForQueuedThread(PublicSemaphore s, Thread t) {
73 long startTime = System.nanoTime();
74 while (!s.hasQueuedThread(t)) {
75 if (millisElapsedSince(startTime) > LONG_DELAY_MS)
76 throw new AssertionFailedError("timed out");
77 Thread.yield();
78 }
79 assertTrue(s.hasQueuedThreads());
80 assertTrue(t.isAlive());
81 }
82
83 /**
84 * Spin-waits until s.hasQueuedThreads() becomes true.
85 */
86 void waitForQueuedThreads(Semaphore s) {
87 long startTime = System.nanoTime();
88 while (!s.hasQueuedThreads()) {
89 if (millisElapsedSince(startTime) > LONG_DELAY_MS)
90 throw new AssertionFailedError("timed out");
91 Thread.yield();
92 }
93 }
94
95 enum AcquireMethod {
96 acquire() {
97 void acquire(Semaphore s) throws InterruptedException {
98 s.acquire();
99 }
100 },
101 acquireN() {
102 void acquire(Semaphore s, int permits) throws InterruptedException {
103 s.acquire(permits);
104 }
105 },
106 acquireUninterruptibly() {
107 void acquire(Semaphore s) {
108 s.acquireUninterruptibly();
109 }
110 },
111 acquireUninterruptiblyN() {
112 void acquire(Semaphore s, int permits) {
113 s.acquireUninterruptibly(permits);
114 }
115 },
116 tryAcquire() {
117 void acquire(Semaphore s) {
118 assertTrue(s.tryAcquire());
119 }
120 },
121 tryAcquireN() {
122 void acquire(Semaphore s, int permits) {
123 assertTrue(s.tryAcquire(permits));
124 }
125 },
126 tryAcquireTimed() {
127 void acquire(Semaphore s) throws InterruptedException {
128 assertTrue(s.tryAcquire(2 * LONG_DELAY_MS, MILLISECONDS));
129 }
130 Thread.State parkedState() { return Thread.State.TIMED_WAITING; }
131 },
132 tryAcquireTimedN {
133 void acquire(Semaphore s, int permits) throws InterruptedException {
134 assertTrue(s.tryAcquire(permits, 2 * LONG_DELAY_MS, MILLISECONDS));
135 }
136 Thread.State parkedState() { return Thread.State.TIMED_WAITING; }
137 };
138
139 // Intentionally meta-circular
140
141 /** Acquires 1 permit. */
142 void acquire(Semaphore s) throws InterruptedException {
143 acquire(s, 1);
144 }
145 /** Acquires the given number of permits. */
146 void acquire(Semaphore s, int permits) throws InterruptedException {
147 for (int i = 0; i < permits; i++)
148 acquire(s);
149 }
150 Thread.State parkedState() { return Thread.State.WAITING; }
151 }
152
153 /**
154 * Zero, negative, and positive initial values are allowed in constructor
155 */
156 public void testConstructor() { testConstructor(false); }
157 public void testConstructor_fair() { testConstructor(true); }
158 public void testConstructor(boolean fair) {
159 for (int permits : new int[] { -42, -1, 0, 1, 42 }) {
160 Semaphore s = new Semaphore(permits, fair);
161 assertEquals(permits, s.availablePermits());
162 assertEquals(fair, s.isFair());
163 }
164 }
165
166 /**
167 * Constructor without fairness argument behaves as nonfair
168 */
169 public void testConstructorDefaultsToNonFair() {
170 for (int permits : new int[] { -42, -1, 0, 1, 42 }) {
171 Semaphore s = new Semaphore(permits);
172 assertEquals(permits, s.availablePermits());
173 assertFalse(s.isFair());
174 }
175 }
176
177 /**
178 * tryAcquire succeeds when sufficient permits, else fails
179 */
180 public void testTryAcquireInSameThread() { testTryAcquireInSameThread(false); }
181 public void testTryAcquireInSameThread_fair() { testTryAcquireInSameThread(true); }
182 public void testTryAcquireInSameThread(boolean fair) {
183 Semaphore s = new Semaphore(2, fair);
184 assertEquals(2, s.availablePermits());
185 assertTrue(s.tryAcquire());
186 assertTrue(s.tryAcquire());
187 assertEquals(0, s.availablePermits());
188 assertFalse(s.tryAcquire());
189 assertFalse(s.tryAcquire());
190 assertEquals(0, s.availablePermits());
191 }
192
193 /**
194 * timed tryAcquire times out
195 */
196 public void testTryAcquire_timeout() { testTryAcquire_timeout(false); }
197 public void testTryAcquire_timeout_fair() { testTryAcquire_timeout(true); }
198 public void testTryAcquire_timeout(boolean fair) {
199 Semaphore s = new Semaphore(0, fair);
200 long startTime = System.nanoTime();
201 try { assertFalse(s.tryAcquire(timeoutMillis(), MILLISECONDS)); }
202 catch (InterruptedException e) { threadUnexpectedException(e); }
203 assertTrue(millisElapsedSince(startTime) >= timeoutMillis());
204 }
205
206 /**
207 * timed tryAcquire(N) times out
208 */
209 public void testTryAcquireN_timeout() { testTryAcquireN_timeout(false); }
210 public void testTryAcquireN_timeout_fair() { testTryAcquireN_timeout(true); }
211 public void testTryAcquireN_timeout(boolean fair) {
212 Semaphore s = new Semaphore(2, fair);
213 long startTime = System.nanoTime();
214 try { assertFalse(s.tryAcquire(3, timeoutMillis(), MILLISECONDS)); }
215 catch (InterruptedException e) { threadUnexpectedException(e); }
216 assertTrue(millisElapsedSince(startTime) >= timeoutMillis());
217 }
218
219 /**
220 * acquire(), acquire(N), timed tryAcquired, timed tryAcquire(N)
221 * are interruptible
222 */
223 public void testInterruptible_acquire() { testInterruptible(false, AcquireMethod.acquire); }
224 public void testInterruptible_acquire_fair() { testInterruptible(true, AcquireMethod.acquire); }
225 public void testInterruptible_acquireN() { testInterruptible(false, AcquireMethod.acquireN); }
226 public void testInterruptible_acquireN_fair() { testInterruptible(true, AcquireMethod.acquireN); }
227 public void testInterruptible_tryAcquireTimed() { testInterruptible(false, AcquireMethod.tryAcquireTimed); }
228 public void testInterruptible_tryAcquireTimed_fair() { testInterruptible(true, AcquireMethod.tryAcquireTimed); }
229 public void testInterruptible_tryAcquireTimedN() { testInterruptible(false, AcquireMethod.tryAcquireTimedN); }
230 public void testInterruptible_tryAcquireTimedN_fair() { testInterruptible(true, AcquireMethod.tryAcquireTimedN); }
231 public void testInterruptible(boolean fair, final AcquireMethod acquirer) {
232 final PublicSemaphore s = new PublicSemaphore(0, fair);
233 final java.util.concurrent.CyclicBarrier pleaseInterrupt
234 = new java.util.concurrent.CyclicBarrier(2);
235 Thread t = newStartedThread(new CheckedRunnable() {
236 public void realRun() {
237 // Interrupt before acquire
238 Thread.currentThread().interrupt();
239 try {
240 acquirer.acquire(s);
241 shouldThrow();
242 } catch (InterruptedException success) {}
243 assertFalse(Thread.interrupted());
244
245 // Interrupt before acquire(N)
246 Thread.currentThread().interrupt();
247 try {
248 acquirer.acquire(s, 3);
249 shouldThrow();
250 } catch (InterruptedException success) {}
251 assertFalse(Thread.interrupted());
252
253 // Interrupt during acquire
254 await(pleaseInterrupt);
255 try {
256 acquirer.acquire(s);
257 shouldThrow();
258 } catch (InterruptedException success) {}
259 assertFalse(Thread.interrupted());
260
261 // Interrupt during acquire(N)
262 await(pleaseInterrupt);
263 try {
264 acquirer.acquire(s, 3);
265 shouldThrow();
266 } catch (InterruptedException success) {}
267 assertFalse(Thread.interrupted());
268 }});
269
270 for (int n = 2; n-->0; ) {
271 await(pleaseInterrupt);
272 assertThreadBlocks(t, acquirer.parkedState());
273 t.interrupt();
274 }
275
276 awaitTermination(t);
277 }
278
279 /**
280 * acquireUninterruptibly(), acquireUninterruptibly(N) are
281 * uninterruptible
282 */
283 public void testUninterruptible_acquireUninterruptibly() { testUninterruptible(false, AcquireMethod.acquireUninterruptibly); }
284 public void testUninterruptible_acquireUninterruptibly_fair() { testUninterruptible(true, AcquireMethod.acquireUninterruptibly); }
285 public void testUninterruptible_acquireUninterruptiblyN() { testUninterruptible(false, AcquireMethod.acquireUninterruptiblyN); }
286 public void testUninterruptible_acquireUninterruptiblyN_fair() { testUninterruptible(true, AcquireMethod.acquireUninterruptiblyN); }
287 public void testUninterruptible(boolean fair, final AcquireMethod acquirer) {
288 final PublicSemaphore s = new PublicSemaphore(0, fair);
289 final Semaphore pleaseInterrupt = new Semaphore(-1, fair);
290
291 Thread t1 = newStartedThread(new CheckedRunnable() {
292 public void realRun() throws InterruptedException {
293 // Interrupt before acquire
294 pleaseInterrupt.release();
295 Thread.currentThread().interrupt();
296 acquirer.acquire(s);
297 assertTrue(Thread.interrupted());
298 }});
299
300 Thread t2 = newStartedThread(new CheckedRunnable() {
301 public void realRun() throws InterruptedException {
302 // Interrupt during acquire
303 pleaseInterrupt.release();
304 acquirer.acquire(s);
305 assertTrue(Thread.interrupted());
306 }});
307
308 await(pleaseInterrupt);
309 waitForQueuedThread(s, t1);
310 waitForQueuedThread(s, t2);
311 t2.interrupt();
312
313 assertThreadBlocks(t1, Thread.State.WAITING);
314 assertThreadBlocks(t2, Thread.State.WAITING);
315
316 s.release(2);
317
318 awaitTermination(t1);
319 awaitTermination(t2);
320 }
321
322 /**
323 * hasQueuedThreads reports whether there are waiting threads
324 */
325 public void testHasQueuedThreads() { testHasQueuedThreads(false); }
326 public void testHasQueuedThreads_fair() { testHasQueuedThreads(true); }
327 public void testHasQueuedThreads(boolean fair) {
328 final PublicSemaphore lock = new PublicSemaphore(1, fair);
329 assertFalse(lock.hasQueuedThreads());
330 lock.acquireUninterruptibly();
331 Thread t1 = newStartedThread(new InterruptedLockRunnable(lock));
332 waitForQueuedThread(lock, t1);
333 assertTrue(lock.hasQueuedThreads());
334 Thread t2 = newStartedThread(new InterruptibleLockRunnable(lock));
335 waitForQueuedThread(lock, t2);
336 assertTrue(lock.hasQueuedThreads());
337 t1.interrupt();
338 awaitTermination(t1);
339 assertTrue(lock.hasQueuedThreads());
340 lock.release();
341 awaitTermination(t2);
342 assertFalse(lock.hasQueuedThreads());
343 }
344
345 /**
346 * getQueueLength reports number of waiting threads
347 */
348 public void testGetQueueLength() { testGetQueueLength(false); }
349 public void testGetQueueLength_fair() { testGetQueueLength(true); }
350 public void testGetQueueLength(boolean fair) {
351 final PublicSemaphore lock = new PublicSemaphore(1, fair);
352 assertEquals(0, lock.getQueueLength());
353 lock.acquireUninterruptibly();
354 Thread t1 = newStartedThread(new InterruptedLockRunnable(lock));
355 waitForQueuedThread(lock, t1);
356 assertEquals(1, lock.getQueueLength());
357 Thread t2 = newStartedThread(new InterruptibleLockRunnable(lock));
358 waitForQueuedThread(lock, t2);
359 assertEquals(2, lock.getQueueLength());
360 t1.interrupt();
361 awaitTermination(t1);
362 assertEquals(1, lock.getQueueLength());
363 lock.release();
364 awaitTermination(t2);
365 assertEquals(0, lock.getQueueLength());
366 }
367
368 /**
369 * getQueuedThreads includes waiting threads
370 */
371 public void testGetQueuedThreads() { testGetQueuedThreads(false); }
372 public void testGetQueuedThreads_fair() { testGetQueuedThreads(true); }
373 public void testGetQueuedThreads(boolean fair) {
374 final PublicSemaphore lock = new PublicSemaphore(1, fair);
375 assertTrue(lock.getQueuedThreads().isEmpty());
376 lock.acquireUninterruptibly();
377 assertTrue(lock.getQueuedThreads().isEmpty());
378 Thread t1 = newStartedThread(new InterruptedLockRunnable(lock));
379 waitForQueuedThread(lock, t1);
380 assertTrue(lock.getQueuedThreads().contains(t1));
381 Thread t2 = newStartedThread(new InterruptibleLockRunnable(lock));
382 waitForQueuedThread(lock, t2);
383 assertTrue(lock.getQueuedThreads().contains(t1));
384 assertTrue(lock.getQueuedThreads().contains(t2));
385 t1.interrupt();
386 awaitTermination(t1);
387 assertFalse(lock.getQueuedThreads().contains(t1));
388 assertTrue(lock.getQueuedThreads().contains(t2));
389 lock.release();
390 awaitTermination(t2);
391 assertTrue(lock.getQueuedThreads().isEmpty());
392 }
393
394 /**
395 * drainPermits reports and removes given number of permits
396 */
397 public void testDrainPermits() { testDrainPermits(false); }
398 public void testDrainPermits_fair() { testDrainPermits(true); }
399 public void testDrainPermits(boolean fair) {
400 Semaphore s = new Semaphore(0, fair);
401 assertEquals(0, s.availablePermits());
402 assertEquals(0, s.drainPermits());
403 s.release(10);
404 assertEquals(10, s.availablePermits());
405 assertEquals(10, s.drainPermits());
406 assertEquals(0, s.availablePermits());
407 assertEquals(0, s.drainPermits());
408 }
409
410 /**
411 * release(-N) throws IllegalArgumentException
412 */
413 public void testReleaseIAE() { testReleaseIAE(false); }
414 public void testReleaseIAE_fair() { testReleaseIAE(true); }
415 public void testReleaseIAE(boolean fair) {
416 Semaphore s = new Semaphore(10, fair);
417 try {
418 s.release(-1);
419 shouldThrow();
420 } catch (IllegalArgumentException success) {}
421 }
422
423 /**
424 * reducePermits(-N) throws IllegalArgumentException
425 */
426 public void testReducePermitsIAE() { testReducePermitsIAE(false); }
427 public void testReducePermitsIAE_fair() { testReducePermitsIAE(true); }
428 public void testReducePermitsIAE(boolean fair) {
429 PublicSemaphore s = new PublicSemaphore(10, fair);
430 try {
431 s.reducePermits(-1);
432 shouldThrow();
433 } catch (IllegalArgumentException success) {}
434 }
435
436 /**
437 * reducePermits reduces number of permits
438 */
439 public void testReducePermits() { testReducePermits(false); }
440 public void testReducePermits_fair() { testReducePermits(true); }
441 public void testReducePermits(boolean fair) {
442 PublicSemaphore s = new PublicSemaphore(10, fair);
443 assertEquals(10, s.availablePermits());
444 s.reducePermits(0);
445 assertEquals(10, s.availablePermits());
446 s.reducePermits(1);
447 assertEquals(9, s.availablePermits());
448 s.reducePermits(10);
449 assertEquals(-1, s.availablePermits());
450 s.reducePermits(10);
451 assertEquals(-11, s.availablePermits());
452 s.reducePermits(0);
453 assertEquals(-11, s.availablePermits());
454 }
455
456 /**
457 * a reserialized semaphore has same number of permits and
458 * fairness, but no queued threads
459 */
460 public void testSerialization() { testSerialization(false); }
461 public void testSerialization_fair() { testSerialization(true); }
462 public void testSerialization(boolean fair) {
463 try {
464 Semaphore s = new Semaphore(3, fair);
465 s.acquire();
466 s.acquire();
467 s.release();
468
469 Semaphore clone = serialClone(s);
470 assertEquals(fair, s.isFair());
471 assertEquals(fair, clone.isFair());
472 assertEquals(2, s.availablePermits());
473 assertEquals(2, clone.availablePermits());
474 clone.acquire();
475 clone.acquire();
476 clone.release();
477 assertEquals(2, s.availablePermits());
478 assertEquals(1, clone.availablePermits());
479 assertFalse(s.hasQueuedThreads());
480 assertFalse(clone.hasQueuedThreads());
481 } catch (InterruptedException e) { threadUnexpectedException(e); }
482
483 {
484 PublicSemaphore s = new PublicSemaphore(0, fair);
485 Thread t = newStartedThread(new InterruptibleLockRunnable(s));
486 // waitForQueuedThreads(s); // suffers from "flicker", so ...
487 waitForQueuedThread(s, t); // ... we use this instead
488 PublicSemaphore clone = serialClone(s);
489 assertEquals(fair, s.isFair());
490 assertEquals(fair, clone.isFair());
491 assertEquals(0, s.availablePermits());
492 assertEquals(0, clone.availablePermits());
493 assertTrue(s.hasQueuedThreads());
494 assertFalse(clone.hasQueuedThreads());
495 s.release();
496 awaitTermination(t);
497 assertFalse(s.hasQueuedThreads());
498 assertFalse(clone.hasQueuedThreads());
499 }
500 }
501
502 /**
503 * tryAcquire(n) succeeds when sufficient permits, else fails
504 */
505 public void testTryAcquireNInSameThread() { testTryAcquireNInSameThread(false); }
506 public void testTryAcquireNInSameThread_fair() { testTryAcquireNInSameThread(true); }
507 public void testTryAcquireNInSameThread(boolean fair) {
508 Semaphore s = new Semaphore(2, fair);
509 assertEquals(2, s.availablePermits());
510 assertFalse(s.tryAcquire(3));
511 assertEquals(2, s.availablePermits());
512 assertTrue(s.tryAcquire(2));
513 assertEquals(0, s.availablePermits());
514 assertFalse(s.tryAcquire(1));
515 assertFalse(s.tryAcquire(2));
516 assertEquals(0, s.availablePermits());
517 }
518
519 /**
520 * acquire succeeds if permits available
521 */
522 public void testReleaseAcquireSameThread_acquire() { testReleaseAcquireSameThread(false, AcquireMethod.acquire); }
523 public void testReleaseAcquireSameThread_acquire_fair() { testReleaseAcquireSameThread(true, AcquireMethod.acquire); }
524 public void testReleaseAcquireSameThread_acquireN() { testReleaseAcquireSameThread(false, AcquireMethod.acquireN); }
525 public void testReleaseAcquireSameThread_acquireN_fair() { testReleaseAcquireSameThread(true, AcquireMethod.acquireN); }
526 public void testReleaseAcquireSameThread_acquireUninterruptibly() { testReleaseAcquireSameThread(false, AcquireMethod.acquireUninterruptibly); }
527 public void testReleaseAcquireSameThread_acquireUninterruptibly_fair() { testReleaseAcquireSameThread(true, AcquireMethod.acquireUninterruptibly); }
528 public void testReleaseAcquireSameThread_acquireUninterruptiblyN() { testReleaseAcquireSameThread(false, AcquireMethod.acquireUninterruptibly); }
529 public void testReleaseAcquireSameThread_acquireUninterruptiblyN_fair() { testReleaseAcquireSameThread(true, AcquireMethod.acquireUninterruptibly); }
530 public void testReleaseAcquireSameThread_tryAcquire() { testReleaseAcquireSameThread(false, AcquireMethod.tryAcquire); }
531 public void testReleaseAcquireSameThread_tryAcquire_fair() { testReleaseAcquireSameThread(true, AcquireMethod.tryAcquire); }
532 public void testReleaseAcquireSameThread_tryAcquireN() { testReleaseAcquireSameThread(false, AcquireMethod.tryAcquireN); }
533 public void testReleaseAcquireSameThread_tryAcquireN_fair() { testReleaseAcquireSameThread(true, AcquireMethod.tryAcquireN); }
534 public void testReleaseAcquireSameThread_tryAcquireTimed() { testReleaseAcquireSameThread(false, AcquireMethod.tryAcquireTimed); }
535 public void testReleaseAcquireSameThread_tryAcquireTimed_fair() { testReleaseAcquireSameThread(true, AcquireMethod.tryAcquireTimed); }
536 public void testReleaseAcquireSameThread_tryAcquireTimedN() { testReleaseAcquireSameThread(false, AcquireMethod.tryAcquireTimedN); }
537 public void testReleaseAcquireSameThread_tryAcquireTimedN_fair() { testReleaseAcquireSameThread(true, AcquireMethod.tryAcquireTimedN); }
538 public void testReleaseAcquireSameThread(boolean fair,
539 final AcquireMethod acquirer) {
540 Semaphore s = new Semaphore(1, fair);
541 for (int i = 1; i < 6; i++) {
542 s.release(i);
543 assertEquals(1 + i, s.availablePermits());
544 try {
545 acquirer.acquire(s, i);
546 } catch (InterruptedException e) { threadUnexpectedException(e); }
547 assertEquals(1, s.availablePermits());
548 }
549 }
550
551 /**
552 * release in one thread enables acquire in another thread
553 */
554 public void testReleaseAcquireDifferentThreads_acquire() { testReleaseAcquireDifferentThreads(false, AcquireMethod.acquire); }
555 public void testReleaseAcquireDifferentThreads_acquire_fair() { testReleaseAcquireDifferentThreads(true, AcquireMethod.acquire); }
556 public void testReleaseAcquireDifferentThreads_acquireN() { testReleaseAcquireDifferentThreads(false, AcquireMethod.acquireN); }
557 public void testReleaseAcquireDifferentThreads_acquireN_fair() { testReleaseAcquireDifferentThreads(true, AcquireMethod.acquireN); }
558 public void testReleaseAcquireDifferentThreads_acquireUninterruptibly() { testReleaseAcquireDifferentThreads(false, AcquireMethod.acquireUninterruptibly); }
559 public void testReleaseAcquireDifferentThreads_acquireUninterruptibly_fair() { testReleaseAcquireDifferentThreads(true, AcquireMethod.acquireUninterruptibly); }
560 public void testReleaseAcquireDifferentThreads_acquireUninterruptiblyN() { testReleaseAcquireDifferentThreads(false, AcquireMethod.acquireUninterruptibly); }
561 public void testReleaseAcquireDifferentThreads_acquireUninterruptiblyN_fair() { testReleaseAcquireDifferentThreads(true, AcquireMethod.acquireUninterruptibly); }
562 public void testReleaseAcquireDifferentThreads_tryAcquireTimed() { testReleaseAcquireDifferentThreads(false, AcquireMethod.tryAcquireTimed); }
563 public void testReleaseAcquireDifferentThreads_tryAcquireTimed_fair() { testReleaseAcquireDifferentThreads(true, AcquireMethod.tryAcquireTimed); }
564 public void testReleaseAcquireDifferentThreads_tryAcquireTimedN() { testReleaseAcquireDifferentThreads(false, AcquireMethod.tryAcquireTimedN); }
565 public void testReleaseAcquireDifferentThreads_tryAcquireTimedN_fair() { testReleaseAcquireDifferentThreads(true, AcquireMethod.tryAcquireTimedN); }
566 public void testReleaseAcquireDifferentThreads(boolean fair,
567 final AcquireMethod acquirer) {
568 final Semaphore s = new Semaphore(0, fair);
569 final int rounds = 4;
570 long startTime = System.nanoTime();
571 Thread t = newStartedThread(new CheckedRunnable() {
572 public void realRun() throws InterruptedException {
573 for (int i = 0; i < rounds; i++) {
574 assertFalse(s.hasQueuedThreads());
575 if (i % 2 == 0)
576 acquirer.acquire(s);
577 else
578 acquirer.acquire(s, 3);
579 }}});
580
581 for (int i = 0; i < rounds; i++) {
582 while (! (s.availablePermits() == 0 && s.hasQueuedThreads()))
583 Thread.yield();
584 assertTrue(t.isAlive());
585 if (i % 2 == 0)
586 s.release();
587 else
588 s.release(3);
589 }
590 awaitTermination(t);
591 assertEquals(0, s.availablePermits());
592 assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS);
593 }
594
595 /**
596 * fair locks are strictly FIFO
597 */
598 public void testFairLocksFifo() {
599 final PublicSemaphore s = new PublicSemaphore(1, true);
600 final CountDownLatch pleaseRelease = new CountDownLatch(1);
601 Thread t1 = newStartedThread(new CheckedRunnable() {
602 public void realRun() throws InterruptedException {
603 // Will block; permits are available, but not three
604 s.acquire(3);
605 }});
606
607 waitForQueuedThread(s, t1);
608
609 Thread t2 = newStartedThread(new CheckedRunnable() {
610 public void realRun() throws InterruptedException {
611 // Will fail, even though 1 permit is available
612 assertFalse(s.tryAcquire(0L, MILLISECONDS));
613 assertFalse(s.tryAcquire(1, 0L, MILLISECONDS));
614
615 // untimed tryAcquire will barge and succeed
616 assertTrue(s.tryAcquire());
617 s.release(2);
618 assertTrue(s.tryAcquire(2));
619 s.release();
620
621 pleaseRelease.countDown();
622 // Will queue up behind t1, even though 1 permit is available
623 s.acquire();
624 }});
625
626 await(pleaseRelease);
627 waitForQueuedThread(s, t2);
628 s.release(2);
629 awaitTermination(t1);
630 assertTrue(t2.isAlive());
631 s.release();
632 awaitTermination(t2);
633 }
634
635 /**
636 * toString indicates current number of permits
637 */
638 public void testToString() { testToString(false); }
639 public void testToString_fair() { testToString(true); }
640 public void testToString(boolean fair) {
641 PublicSemaphore s = new PublicSemaphore(0, fair);
642 assertTrue(s.toString().contains("Permits = 0"));
643 s.release();
644 assertTrue(s.toString().contains("Permits = 1"));
645 s.release(2);
646 assertTrue(s.toString().contains("Permits = 3"));
647 s.reducePermits(5);
648 assertTrue(s.toString().contains("Permits = -2"));
649 }
650
651 }