ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/test/tck/SemaphoreTest.java
Revision: 1.39
Committed: Sun May 14 03:31:53 2017 UTC (7 years ago) by jsr166
Branch: MAIN
Changes since 1.38: +11 -10 lines
Log Message:
switch to randomized fairness for tests that block

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