ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/test/tck/SemaphoreTest.java
Revision: 1.45
Committed: Tue Aug 13 00:46:27 2019 UTC (4 years, 8 months ago) by jsr166
Branch: MAIN
CVS Tags: HEAD
Changes since 1.44: +0 -1 lines
Log Message:
fix imports

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