ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/test/tck/SemaphoreTest.java
Revision: 1.42
Committed: Mon May 29 19:15:03 2017 UTC (6 years, 11 months ago) by jsr166
Branch: MAIN
Changes since 1.41: +4 -2 lines
Log Message:
more timeout handling rework; remove most uses of SMALL_DELAY_MS; randomize timeouts and TimeUnits; remove hardcoded 5 second timeouts

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 boolean fair = ThreadLocalRandom.current().nextBoolean();
199 final Semaphore s = new Semaphore(0, fair);
200 final 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() {
210 final boolean fair = ThreadLocalRandom.current().nextBoolean();
211 final Semaphore s = new Semaphore(2, fair);
212 final long startTime = System.nanoTime();
213 try { assertFalse(s.tryAcquire(3, timeoutMillis(), MILLISECONDS)); }
214 catch (InterruptedException e) { threadUnexpectedException(e); }
215 assertTrue(millisElapsedSince(startTime) >= timeoutMillis());
216 }
217
218 /**
219 * acquire(), acquire(N), timed tryAcquired, timed tryAcquire(N)
220 * are interruptible
221 */
222 public void testInterruptible_acquire() { testInterruptible(false, AcquireMethod.acquire); }
223 public void testInterruptible_acquire_fair() { testInterruptible(true, AcquireMethod.acquire); }
224 public void testInterruptible_acquireN() { testInterruptible(false, AcquireMethod.acquireN); }
225 public void testInterruptible_acquireN_fair() { testInterruptible(true, AcquireMethod.acquireN); }
226 public void testInterruptible_tryAcquireTimed() { testInterruptible(false, AcquireMethod.tryAcquireTimed); }
227 public void testInterruptible_tryAcquireTimed_fair() { testInterruptible(true, AcquireMethod.tryAcquireTimed); }
228 public void testInterruptible_tryAcquireTimedN() { testInterruptible(false, AcquireMethod.tryAcquireTimedN); }
229 public void testInterruptible_tryAcquireTimedN_fair() { testInterruptible(true, AcquireMethod.tryAcquireTimedN); }
230 public void testInterruptible(boolean fair, final AcquireMethod acquirer) {
231 final PublicSemaphore s = new PublicSemaphore(0, fair);
232 final java.util.concurrent.CyclicBarrier pleaseInterrupt
233 = new java.util.concurrent.CyclicBarrier(2);
234 Thread t = newStartedThread(new CheckedRunnable() {
235 public void realRun() {
236 // Interrupt before acquire
237 Thread.currentThread().interrupt();
238 try {
239 acquirer.acquire(s);
240 shouldThrow();
241 } catch (InterruptedException success) {}
242 assertFalse(Thread.interrupted());
243
244 // Interrupt before acquire(N)
245 Thread.currentThread().interrupt();
246 try {
247 acquirer.acquire(s, 3);
248 shouldThrow();
249 } catch (InterruptedException success) {}
250 assertFalse(Thread.interrupted());
251
252 // Interrupt during acquire
253 await(pleaseInterrupt);
254 try {
255 acquirer.acquire(s);
256 shouldThrow();
257 } catch (InterruptedException success) {}
258 assertFalse(Thread.interrupted());
259
260 // Interrupt during acquire(N)
261 await(pleaseInterrupt);
262 try {
263 acquirer.acquire(s, 3);
264 shouldThrow();
265 } catch (InterruptedException success) {}
266 assertFalse(Thread.interrupted());
267 }});
268
269 for (int n = 2; n-->0; ) {
270 await(pleaseInterrupt);
271 assertThreadBlocks(t, acquirer.parkedState());
272 t.interrupt();
273 }
274
275 awaitTermination(t);
276 }
277
278 /**
279 * acquireUninterruptibly(), acquireUninterruptibly(N) are
280 * uninterruptible
281 */
282 public void testUninterruptible_acquireUninterruptibly() { testUninterruptible(false, AcquireMethod.acquireUninterruptibly); }
283 public void testUninterruptible_acquireUninterruptibly_fair() { testUninterruptible(true, AcquireMethod.acquireUninterruptibly); }
284 public void testUninterruptible_acquireUninterruptiblyN() { testUninterruptible(false, AcquireMethod.acquireUninterruptiblyN); }
285 public void testUninterruptible_acquireUninterruptiblyN_fair() { testUninterruptible(true, AcquireMethod.acquireUninterruptiblyN); }
286 public void testUninterruptible(boolean fair, final AcquireMethod acquirer) {
287 final PublicSemaphore s = new PublicSemaphore(0, fair);
288 final Semaphore pleaseInterrupt = new Semaphore(-1, fair);
289
290 Thread t1 = newStartedThread(new CheckedRunnable() {
291 public void realRun() throws InterruptedException {
292 // Interrupt before acquire
293 pleaseInterrupt.release();
294 Thread.currentThread().interrupt();
295 acquirer.acquire(s);
296 assertTrue(Thread.interrupted());
297 }});
298
299 Thread t2 = newStartedThread(new CheckedRunnable() {
300 public void realRun() throws InterruptedException {
301 // Interrupt during acquire
302 pleaseInterrupt.release();
303 acquirer.acquire(s);
304 assertTrue(Thread.interrupted());
305 }});
306
307 await(pleaseInterrupt);
308 waitForQueuedThread(s, t1);
309 waitForQueuedThread(s, t2);
310 t2.interrupt();
311
312 assertThreadBlocks(t1, Thread.State.WAITING);
313 assertThreadBlocks(t2, Thread.State.WAITING);
314
315 s.release(2);
316
317 awaitTermination(t1);
318 awaitTermination(t2);
319 }
320
321 /**
322 * hasQueuedThreads reports whether there are waiting threads
323 */
324 public void testHasQueuedThreads() { testHasQueuedThreads(false); }
325 public void testHasQueuedThreads_fair() { testHasQueuedThreads(true); }
326 public void testHasQueuedThreads(boolean fair) {
327 final PublicSemaphore lock = new PublicSemaphore(1, fair);
328 assertFalse(lock.hasQueuedThreads());
329 lock.acquireUninterruptibly();
330 Thread t1 = newStartedThread(new InterruptedLockRunnable(lock));
331 waitForQueuedThread(lock, t1);
332 assertTrue(lock.hasQueuedThreads());
333 Thread t2 = newStartedThread(new InterruptibleLockRunnable(lock));
334 waitForQueuedThread(lock, t2);
335 assertTrue(lock.hasQueuedThreads());
336 t1.interrupt();
337 awaitTermination(t1);
338 assertTrue(lock.hasQueuedThreads());
339 lock.release();
340 awaitTermination(t2);
341 assertFalse(lock.hasQueuedThreads());
342 }
343
344 /**
345 * getQueueLength reports number of waiting threads
346 */
347 public void testGetQueueLength() { testGetQueueLength(false); }
348 public void testGetQueueLength_fair() { testGetQueueLength(true); }
349 public void testGetQueueLength(boolean fair) {
350 final PublicSemaphore lock = new PublicSemaphore(1, fair);
351 assertEquals(0, lock.getQueueLength());
352 lock.acquireUninterruptibly();
353 Thread t1 = newStartedThread(new InterruptedLockRunnable(lock));
354 waitForQueuedThread(lock, t1);
355 assertEquals(1, lock.getQueueLength());
356 Thread t2 = newStartedThread(new InterruptibleLockRunnable(lock));
357 waitForQueuedThread(lock, t2);
358 assertEquals(2, lock.getQueueLength());
359 t1.interrupt();
360 awaitTermination(t1);
361 assertEquals(1, lock.getQueueLength());
362 lock.release();
363 awaitTermination(t2);
364 assertEquals(0, lock.getQueueLength());
365 }
366
367 /**
368 * getQueuedThreads includes waiting threads
369 */
370 public void testGetQueuedThreads() { testGetQueuedThreads(false); }
371 public void testGetQueuedThreads_fair() { testGetQueuedThreads(true); }
372 public void testGetQueuedThreads(boolean fair) {
373 final PublicSemaphore lock = new PublicSemaphore(1, fair);
374 assertTrue(lock.getQueuedThreads().isEmpty());
375 lock.acquireUninterruptibly();
376 assertTrue(lock.getQueuedThreads().isEmpty());
377 Thread t1 = newStartedThread(new InterruptedLockRunnable(lock));
378 waitForQueuedThread(lock, t1);
379 assertTrue(lock.getQueuedThreads().contains(t1));
380 Thread t2 = newStartedThread(new InterruptibleLockRunnable(lock));
381 waitForQueuedThread(lock, t2);
382 assertTrue(lock.getQueuedThreads().contains(t1));
383 assertTrue(lock.getQueuedThreads().contains(t2));
384 t1.interrupt();
385 awaitTermination(t1);
386 assertFalse(lock.getQueuedThreads().contains(t1));
387 assertTrue(lock.getQueuedThreads().contains(t2));
388 lock.release();
389 awaitTermination(t2);
390 assertTrue(lock.getQueuedThreads().isEmpty());
391 }
392
393 /**
394 * drainPermits reports and removes given number of permits
395 */
396 public void testDrainPermits() { testDrainPermits(false); }
397 public void testDrainPermits_fair() { testDrainPermits(true); }
398 public void testDrainPermits(boolean fair) {
399 Semaphore s = new Semaphore(0, fair);
400 assertEquals(0, s.availablePermits());
401 assertEquals(0, s.drainPermits());
402 s.release(10);
403 assertEquals(10, s.availablePermits());
404 assertEquals(10, s.drainPermits());
405 assertEquals(0, s.availablePermits());
406 assertEquals(0, s.drainPermits());
407 }
408
409 /**
410 * release(-N) throws IllegalArgumentException
411 */
412 public void testReleaseIAE() { testReleaseIAE(false); }
413 public void testReleaseIAE_fair() { testReleaseIAE(true); }
414 public void testReleaseIAE(boolean fair) {
415 Semaphore s = new Semaphore(10, fair);
416 try {
417 s.release(-1);
418 shouldThrow();
419 } catch (IllegalArgumentException success) {}
420 }
421
422 /**
423 * reducePermits(-N) throws IllegalArgumentException
424 */
425 public void testReducePermitsIAE() { testReducePermitsIAE(false); }
426 public void testReducePermitsIAE_fair() { testReducePermitsIAE(true); }
427 public void testReducePermitsIAE(boolean fair) {
428 PublicSemaphore s = new PublicSemaphore(10, fair);
429 try {
430 s.reducePermits(-1);
431 shouldThrow();
432 } catch (IllegalArgumentException success) {}
433 }
434
435 /**
436 * reducePermits reduces number of permits
437 */
438 public void testReducePermits() { testReducePermits(false); }
439 public void testReducePermits_fair() { testReducePermits(true); }
440 public void testReducePermits(boolean fair) {
441 PublicSemaphore s = new PublicSemaphore(10, fair);
442 assertEquals(10, s.availablePermits());
443 s.reducePermits(0);
444 assertEquals(10, s.availablePermits());
445 s.reducePermits(1);
446 assertEquals(9, s.availablePermits());
447 s.reducePermits(10);
448 assertEquals(-1, s.availablePermits());
449 s.reducePermits(10);
450 assertEquals(-11, s.availablePermits());
451 s.reducePermits(0);
452 assertEquals(-11, s.availablePermits());
453 }
454
455 /**
456 * a reserialized semaphore has same number of permits and
457 * fairness, but no queued threads
458 */
459 public void testSerialization() { testSerialization(false); }
460 public void testSerialization_fair() { testSerialization(true); }
461 public void testSerialization(boolean fair) {
462 try {
463 Semaphore s = new Semaphore(3, fair);
464 s.acquire();
465 s.acquire();
466 s.release();
467
468 Semaphore clone = serialClone(s);
469 assertEquals(fair, s.isFair());
470 assertEquals(fair, clone.isFair());
471 assertEquals(2, s.availablePermits());
472 assertEquals(2, clone.availablePermits());
473 clone.acquire();
474 clone.acquire();
475 clone.release();
476 assertEquals(2, s.availablePermits());
477 assertEquals(1, clone.availablePermits());
478 assertFalse(s.hasQueuedThreads());
479 assertFalse(clone.hasQueuedThreads());
480 } catch (InterruptedException e) { threadUnexpectedException(e); }
481
482 {
483 PublicSemaphore s = new PublicSemaphore(0, fair);
484 Thread t = newStartedThread(new InterruptibleLockRunnable(s));
485 // waitForQueuedThreads(s); // suffers from "flicker", so ...
486 waitForQueuedThread(s, t); // ... we use this instead
487 PublicSemaphore clone = serialClone(s);
488 assertEquals(fair, s.isFair());
489 assertEquals(fair, clone.isFair());
490 assertEquals(0, s.availablePermits());
491 assertEquals(0, clone.availablePermits());
492 assertTrue(s.hasQueuedThreads());
493 assertFalse(clone.hasQueuedThreads());
494 s.release();
495 awaitTermination(t);
496 assertFalse(s.hasQueuedThreads());
497 assertFalse(clone.hasQueuedThreads());
498 }
499 }
500
501 /**
502 * tryAcquire(n) succeeds when sufficient permits, else fails
503 */
504 public void testTryAcquireNInSameThread() { testTryAcquireNInSameThread(false); }
505 public void testTryAcquireNInSameThread_fair() { testTryAcquireNInSameThread(true); }
506 public void testTryAcquireNInSameThread(boolean fair) {
507 Semaphore s = new Semaphore(2, fair);
508 assertEquals(2, s.availablePermits());
509 assertFalse(s.tryAcquire(3));
510 assertEquals(2, s.availablePermits());
511 assertTrue(s.tryAcquire(2));
512 assertEquals(0, s.availablePermits());
513 assertFalse(s.tryAcquire(1));
514 assertFalse(s.tryAcquire(2));
515 assertEquals(0, s.availablePermits());
516 }
517
518 /**
519 * acquire succeeds if permits available
520 */
521 public void testReleaseAcquireSameThread_acquire() { testReleaseAcquireSameThread(false, AcquireMethod.acquire); }
522 public void testReleaseAcquireSameThread_acquire_fair() { testReleaseAcquireSameThread(true, AcquireMethod.acquire); }
523 public void testReleaseAcquireSameThread_acquireN() { testReleaseAcquireSameThread(false, AcquireMethod.acquireN); }
524 public void testReleaseAcquireSameThread_acquireN_fair() { testReleaseAcquireSameThread(true, AcquireMethod.acquireN); }
525 public void testReleaseAcquireSameThread_acquireUninterruptibly() { testReleaseAcquireSameThread(false, AcquireMethod.acquireUninterruptibly); }
526 public void testReleaseAcquireSameThread_acquireUninterruptibly_fair() { testReleaseAcquireSameThread(true, AcquireMethod.acquireUninterruptibly); }
527 public void testReleaseAcquireSameThread_acquireUninterruptiblyN() { testReleaseAcquireSameThread(false, AcquireMethod.acquireUninterruptibly); }
528 public void testReleaseAcquireSameThread_acquireUninterruptiblyN_fair() { testReleaseAcquireSameThread(true, AcquireMethod.acquireUninterruptibly); }
529 public void testReleaseAcquireSameThread_tryAcquire() { testReleaseAcquireSameThread(false, AcquireMethod.tryAcquire); }
530 public void testReleaseAcquireSameThread_tryAcquire_fair() { testReleaseAcquireSameThread(true, AcquireMethod.tryAcquire); }
531 public void testReleaseAcquireSameThread_tryAcquireN() { testReleaseAcquireSameThread(false, AcquireMethod.tryAcquireN); }
532 public void testReleaseAcquireSameThread_tryAcquireN_fair() { testReleaseAcquireSameThread(true, AcquireMethod.tryAcquireN); }
533 public void testReleaseAcquireSameThread_tryAcquireTimed() { testReleaseAcquireSameThread(false, AcquireMethod.tryAcquireTimed); }
534 public void testReleaseAcquireSameThread_tryAcquireTimed_fair() { testReleaseAcquireSameThread(true, AcquireMethod.tryAcquireTimed); }
535 public void testReleaseAcquireSameThread_tryAcquireTimedN() { testReleaseAcquireSameThread(false, AcquireMethod.tryAcquireTimedN); }
536 public void testReleaseAcquireSameThread_tryAcquireTimedN_fair() { testReleaseAcquireSameThread(true, AcquireMethod.tryAcquireTimedN); }
537 public void testReleaseAcquireSameThread(boolean fair,
538 final AcquireMethod acquirer) {
539 Semaphore s = new Semaphore(1, fair);
540 for (int i = 1; i < 6; i++) {
541 s.release(i);
542 assertEquals(1 + i, s.availablePermits());
543 try {
544 acquirer.acquire(s, i);
545 } catch (InterruptedException e) { threadUnexpectedException(e); }
546 assertEquals(1, s.availablePermits());
547 }
548 }
549
550 /**
551 * release in one thread enables acquire in another thread
552 */
553 public void testReleaseAcquireDifferentThreads_acquire() { testReleaseAcquireDifferentThreads(false, AcquireMethod.acquire); }
554 public void testReleaseAcquireDifferentThreads_acquire_fair() { testReleaseAcquireDifferentThreads(true, AcquireMethod.acquire); }
555 public void testReleaseAcquireDifferentThreads_acquireN() { testReleaseAcquireDifferentThreads(false, AcquireMethod.acquireN); }
556 public void testReleaseAcquireDifferentThreads_acquireN_fair() { testReleaseAcquireDifferentThreads(true, AcquireMethod.acquireN); }
557 public void testReleaseAcquireDifferentThreads_acquireUninterruptibly() { testReleaseAcquireDifferentThreads(false, AcquireMethod.acquireUninterruptibly); }
558 public void testReleaseAcquireDifferentThreads_acquireUninterruptibly_fair() { testReleaseAcquireDifferentThreads(true, AcquireMethod.acquireUninterruptibly); }
559 public void testReleaseAcquireDifferentThreads_acquireUninterruptiblyN() { testReleaseAcquireDifferentThreads(false, AcquireMethod.acquireUninterruptibly); }
560 public void testReleaseAcquireDifferentThreads_acquireUninterruptiblyN_fair() { testReleaseAcquireDifferentThreads(true, AcquireMethod.acquireUninterruptibly); }
561 public void testReleaseAcquireDifferentThreads_tryAcquireTimed() { testReleaseAcquireDifferentThreads(false, AcquireMethod.tryAcquireTimed); }
562 public void testReleaseAcquireDifferentThreads_tryAcquireTimed_fair() { testReleaseAcquireDifferentThreads(true, AcquireMethod.tryAcquireTimed); }
563 public void testReleaseAcquireDifferentThreads_tryAcquireTimedN() { testReleaseAcquireDifferentThreads(false, AcquireMethod.tryAcquireTimedN); }
564 public void testReleaseAcquireDifferentThreads_tryAcquireTimedN_fair() { testReleaseAcquireDifferentThreads(true, AcquireMethod.tryAcquireTimedN); }
565 public void testReleaseAcquireDifferentThreads(boolean fair,
566 final AcquireMethod acquirer) {
567 final Semaphore s = new Semaphore(0, fair);
568 final int rounds = 4;
569 long startTime = System.nanoTime();
570 Thread t = newStartedThread(new CheckedRunnable() {
571 public void realRun() throws InterruptedException {
572 for (int i = 0; i < rounds; i++) {
573 assertFalse(s.hasQueuedThreads());
574 if (i % 2 == 0)
575 acquirer.acquire(s);
576 else
577 acquirer.acquire(s, 3);
578 }}});
579
580 for (int i = 0; i < rounds; i++) {
581 while (! (s.availablePermits() == 0 && s.hasQueuedThreads()))
582 Thread.yield();
583 assertTrue(t.isAlive());
584 if (i % 2 == 0)
585 s.release();
586 else
587 s.release(3);
588 }
589 awaitTermination(t);
590 assertEquals(0, s.availablePermits());
591 assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS);
592 }
593
594 /**
595 * fair locks are strictly FIFO
596 */
597 public void testFairLocksFifo() {
598 final PublicSemaphore s = new PublicSemaphore(1, true);
599 final CountDownLatch pleaseRelease = new CountDownLatch(1);
600 Thread t1 = newStartedThread(new CheckedRunnable() {
601 public void realRun() throws InterruptedException {
602 // Will block; permits are available, but not three
603 s.acquire(3);
604 }});
605
606 waitForQueuedThread(s, t1);
607
608 Thread t2 = newStartedThread(new CheckedRunnable() {
609 public void realRun() throws InterruptedException {
610 // Will fail, even though 1 permit is available
611 assertFalse(
612 s.tryAcquire(randomExpiredTimeout(), randomTimeUnit()));
613 assertFalse(
614 s.tryAcquire(1, randomExpiredTimeout(), randomTimeUnit()));
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 }