blob: db4f4b424edcb1e0c498457095f9b6563041ffa5 [file] [log] [blame]
Calin Juravle8f0d92b2013-08-01 17:26:00 +01001/*
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
9package jsr166;
10
Calin Juravle8f0d92b2013-08-01 17:26:00 +010011import static java.util.concurrent.TimeUnit.MILLISECONDS;
12
Narayan Kamath8e9a0e92015-04-28 11:40:00 +010013import java.util.Collection;
14import java.util.concurrent.CountDownLatch;
15import java.util.concurrent.Semaphore;
Calin Juravle8f0d92b2013-08-01 17:26:00 +010016
Narayan Kamath8e9a0e92015-04-28 11:40:00 +010017import junit.framework.AssertionFailedError;
18import junit.framework.Test;
19import junit.framework.TestSuite;
20
21public class SemaphoreTest extends JSR166TestCase {
22 // android-note: Removed because the CTS runner does a bad job of
23 // retrying tests that have suite() declarations.
24 //
25 // public static void main(String[] args) {
26 // main(suite(), args);
27 // }
28 // public static Test suite() {
29 // return new TestSuite(...);
30 // }
Calin Juravle8f0d92b2013-08-01 17:26:00 +010031 /**
32 * Subclass to expose protected methods
33 */
34 static class PublicSemaphore extends Semaphore {
35 PublicSemaphore(int permits) { super(permits); }
36 PublicSemaphore(int permits, boolean fair) { super(permits, fair); }
37 public Collection<Thread> getQueuedThreads() {
38 return super.getQueuedThreads();
39 }
40 public boolean hasQueuedThread(Thread t) {
41 return super.getQueuedThreads().contains(t);
42 }
43 public void reducePermits(int reduction) {
44 super.reducePermits(reduction);
45 }
46 }
47
48 /**
49 * A runnable calling acquire
50 */
51 class InterruptibleLockRunnable extends CheckedRunnable {
52 final Semaphore lock;
53 InterruptibleLockRunnable(Semaphore s) { lock = s; }
54 public void realRun() {
55 try {
56 lock.acquire();
57 }
58 catch (InterruptedException ignored) {}
59 }
60 }
61
62 /**
63 * A runnable calling acquire that expects to be interrupted
64 */
65 class InterruptedLockRunnable extends CheckedInterruptedRunnable {
66 final Semaphore lock;
67 InterruptedLockRunnable(Semaphore s) { lock = s; }
68 public void realRun() throws InterruptedException {
69 lock.acquire();
70 }
71 }
72
73 /**
74 * Spin-waits until s.hasQueuedThread(t) becomes true.
75 */
76 void waitForQueuedThread(PublicSemaphore s, Thread t) {
77 long startTime = System.nanoTime();
78 while (!s.hasQueuedThread(t)) {
79 if (millisElapsedSince(startTime) > LONG_DELAY_MS)
80 throw new AssertionFailedError("timed out");
81 Thread.yield();
82 }
83 assertTrue(s.hasQueuedThreads());
84 assertTrue(t.isAlive());
85 }
86
87 /**
88 * Spin-waits until s.hasQueuedThreads() becomes true.
89 */
90 void waitForQueuedThreads(Semaphore s) {
91 long startTime = System.nanoTime();
92 while (!s.hasQueuedThreads()) {
93 if (millisElapsedSince(startTime) > LONG_DELAY_MS)
94 throw new AssertionFailedError("timed out");
95 Thread.yield();
96 }
97 }
98
99 enum AcquireMethod {
100 acquire() {
101 void acquire(Semaphore s) throws InterruptedException {
102 s.acquire();
103 }
104 },
105 acquireN() {
106 void acquire(Semaphore s, int permits) throws InterruptedException {
107 s.acquire(permits);
108 }
109 },
110 acquireUninterruptibly() {
111 void acquire(Semaphore s) {
112 s.acquireUninterruptibly();
113 }
114 },
115 acquireUninterruptiblyN() {
116 void acquire(Semaphore s, int permits) {
117 s.acquireUninterruptibly(permits);
118 }
119 },
120 tryAcquire() {
121 void acquire(Semaphore s) {
122 assertTrue(s.tryAcquire());
123 }
124 },
125 tryAcquireN() {
126 void acquire(Semaphore s, int permits) {
127 assertTrue(s.tryAcquire(permits));
128 }
129 },
130 tryAcquireTimed() {
131 void acquire(Semaphore s) throws InterruptedException {
132 assertTrue(s.tryAcquire(2 * LONG_DELAY_MS, MILLISECONDS));
133 }
134 },
135 tryAcquireTimedN {
136 void acquire(Semaphore s, int permits) throws InterruptedException {
137 assertTrue(s.tryAcquire(permits, 2 * LONG_DELAY_MS, MILLISECONDS));
138 }
139 };
140
141 // Intentionally meta-circular
142
143 /** Acquires 1 permit. */
144 void acquire(Semaphore s) throws InterruptedException {
145 acquire(s, 1);
146 }
147 /** Acquires the given number of permits. */
148 void acquire(Semaphore s, int permits) throws InterruptedException {
149 for (int i = 0; i < permits; i++)
150 acquire(s);
151 }
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() { testTryAcquire_timeout(false); }
198 public void testTryAcquire_timeout_fair() { testTryAcquire_timeout(true); }
199 public void testTryAcquire_timeout(boolean fair) {
200 Semaphore s = new Semaphore(0, fair);
201 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() { testTryAcquireN_timeout(false); }
211 public void testTryAcquireN_timeout_fair() { testTryAcquireN_timeout(true); }
212 public void testTryAcquireN_timeout(boolean fair) {
213 Semaphore s = new Semaphore(2, fair);
214 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 Semaphore pleaseInterrupt = new Semaphore(0, fair);
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
244 // Interrupt during acquire
245 try {
246 acquirer.acquire(s);
247 shouldThrow();
248 } catch (InterruptedException success) {}
249
250 // Interrupt before acquire(N)
251 Thread.currentThread().interrupt();
252 try {
253 acquirer.acquire(s, 3);
254 shouldThrow();
255 } catch (InterruptedException success) {}
256
257 pleaseInterrupt.release();
258
259 // Interrupt during acquire(N)
260 try {
261 acquirer.acquire(s, 3);
262 shouldThrow();
263 } catch (InterruptedException success) {}
264 }});
265
266 waitForQueuedThread(s, t);
267 t.interrupt();
268 await(pleaseInterrupt);
269 waitForQueuedThread(s, t);
270 t.interrupt();
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 assertThreadStaysAlive(t1);
309 assertTrue(t2.isAlive());
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
475 s = new Semaphore(0, fair);
476 Thread t = newStartedThread(new InterruptibleLockRunnable(s));
477 waitForQueuedThreads(s);
478 clone = serialClone(s);
479 assertEquals(fair, s.isFair());
480 assertEquals(fair, clone.isFair());
481 assertEquals(0, s.availablePermits());
482 assertEquals(0, clone.availablePermits());
483 assertTrue(s.hasQueuedThreads());
484 assertFalse(clone.hasQueuedThreads());
485 s.release();
486 awaitTermination(t);
487 assertFalse(s.hasQueuedThreads());
488 assertFalse(clone.hasQueuedThreads());
489 } catch (InterruptedException e) { threadUnexpectedException(e); }
490 }
491
492 /**
493 * tryAcquire(n) succeeds when sufficient permits, else fails
494 */
495 public void testTryAcquireNInSameThread() { testTryAcquireNInSameThread(false); }
496 public void testTryAcquireNInSameThread_fair() { testTryAcquireNInSameThread(true); }
497 public void testTryAcquireNInSameThread(boolean fair) {
498 Semaphore s = new Semaphore(2, fair);
499 assertEquals(2, s.availablePermits());
500 assertFalse(s.tryAcquire(3));
501 assertEquals(2, s.availablePermits());
502 assertTrue(s.tryAcquire(2));
503 assertEquals(0, s.availablePermits());
504 assertFalse(s.tryAcquire(1));
505 assertFalse(s.tryAcquire(2));
506 assertEquals(0, s.availablePermits());
507 }
508
509 /**
510 * acquire succeeds if permits available
511 */
512 public void testReleaseAcquireSameThread_acquire() { testReleaseAcquireSameThread(false, AcquireMethod.acquire); }
513 public void testReleaseAcquireSameThread_acquire_fair() { testReleaseAcquireSameThread(true, AcquireMethod.acquire); }
514 public void testReleaseAcquireSameThread_acquireN() { testReleaseAcquireSameThread(false, AcquireMethod.acquireN); }
515 public void testReleaseAcquireSameThread_acquireN_fair() { testReleaseAcquireSameThread(true, AcquireMethod.acquireN); }
516 public void testReleaseAcquireSameThread_acquireUninterruptibly() { testReleaseAcquireSameThread(false, AcquireMethod.acquireUninterruptibly); }
517 public void testReleaseAcquireSameThread_acquireUninterruptibly_fair() { testReleaseAcquireSameThread(true, AcquireMethod.acquireUninterruptibly); }
518 public void testReleaseAcquireSameThread_acquireUninterruptiblyN() { testReleaseAcquireSameThread(false, AcquireMethod.acquireUninterruptibly); }
519 public void testReleaseAcquireSameThread_acquireUninterruptiblyN_fair() { testReleaseAcquireSameThread(true, AcquireMethod.acquireUninterruptibly); }
520 public void testReleaseAcquireSameThread_tryAcquire() { testReleaseAcquireSameThread(false, AcquireMethod.tryAcquire); }
521 public void testReleaseAcquireSameThread_tryAcquire_fair() { testReleaseAcquireSameThread(true, AcquireMethod.tryAcquire); }
522 public void testReleaseAcquireSameThread_tryAcquireN() { testReleaseAcquireSameThread(false, AcquireMethod.tryAcquireN); }
523 public void testReleaseAcquireSameThread_tryAcquireN_fair() { testReleaseAcquireSameThread(true, AcquireMethod.tryAcquireN); }
524 public void testReleaseAcquireSameThread_tryAcquireTimed() { testReleaseAcquireSameThread(false, AcquireMethod.tryAcquireTimed); }
525 public void testReleaseAcquireSameThread_tryAcquireTimed_fair() { testReleaseAcquireSameThread(true, AcquireMethod.tryAcquireTimed); }
526 public void testReleaseAcquireSameThread_tryAcquireTimedN() { testReleaseAcquireSameThread(false, AcquireMethod.tryAcquireTimedN); }
527 public void testReleaseAcquireSameThread_tryAcquireTimedN_fair() { testReleaseAcquireSameThread(true, AcquireMethod.tryAcquireTimedN); }
528 public void testReleaseAcquireSameThread(boolean fair,
529 final AcquireMethod acquirer) {
530 Semaphore s = new Semaphore(1, fair);
531 for (int i = 1; i < 6; i++) {
532 s.release(i);
533 assertEquals(1 + i, s.availablePermits());
534 try {
535 acquirer.acquire(s, i);
536 } catch (InterruptedException e) { threadUnexpectedException(e); }
537 assertEquals(1, s.availablePermits());
538 }
539 }
540
541 /**
542 * release in one thread enables acquire in another thread
543 */
544 public void testReleaseAcquireDifferentThreads_acquire() { testReleaseAcquireDifferentThreads(false, AcquireMethod.acquire); }
545 public void testReleaseAcquireDifferentThreads_acquire_fair() { testReleaseAcquireDifferentThreads(true, AcquireMethod.acquire); }
546 public void testReleaseAcquireDifferentThreads_acquireN() { testReleaseAcquireDifferentThreads(false, AcquireMethod.acquireN); }
547 public void testReleaseAcquireDifferentThreads_acquireN_fair() { testReleaseAcquireDifferentThreads(true, AcquireMethod.acquireN); }
548 public void testReleaseAcquireDifferentThreads_acquireUninterruptibly() { testReleaseAcquireDifferentThreads(false, AcquireMethod.acquireUninterruptibly); }
549 public void testReleaseAcquireDifferentThreads_acquireUninterruptibly_fair() { testReleaseAcquireDifferentThreads(true, AcquireMethod.acquireUninterruptibly); }
550 public void testReleaseAcquireDifferentThreads_acquireUninterruptiblyN() { testReleaseAcquireDifferentThreads(false, AcquireMethod.acquireUninterruptibly); }
551 public void testReleaseAcquireDifferentThreads_acquireUninterruptiblyN_fair() { testReleaseAcquireDifferentThreads(true, AcquireMethod.acquireUninterruptibly); }
552 public void testReleaseAcquireDifferentThreads_tryAcquireTimed() { testReleaseAcquireDifferentThreads(false, AcquireMethod.tryAcquireTimed); }
553 public void testReleaseAcquireDifferentThreads_tryAcquireTimed_fair() { testReleaseAcquireDifferentThreads(true, AcquireMethod.tryAcquireTimed); }
554 public void testReleaseAcquireDifferentThreads_tryAcquireTimedN() { testReleaseAcquireDifferentThreads(false, AcquireMethod.tryAcquireTimedN); }
555 public void testReleaseAcquireDifferentThreads_tryAcquireTimedN_fair() { testReleaseAcquireDifferentThreads(true, AcquireMethod.tryAcquireTimedN); }
556 public void testReleaseAcquireDifferentThreads(boolean fair,
557 final AcquireMethod acquirer) {
558 final Semaphore s = new Semaphore(0, fair);
559 final int rounds = 4;
560 long startTime = System.nanoTime();
561 Thread t = newStartedThread(new CheckedRunnable() {
562 public void realRun() throws InterruptedException {
563 for (int i = 0; i < rounds; i++) {
564 assertFalse(s.hasQueuedThreads());
565 if (i % 2 == 0)
566 acquirer.acquire(s);
567 else
568 acquirer.acquire(s, 3);
569 }}});
570
571 for (int i = 0; i < rounds; i++) {
572 while (! (s.availablePermits() == 0 && s.hasQueuedThreads()))
573 Thread.yield();
574 assertTrue(t.isAlive());
575 if (i % 2 == 0)
576 s.release();
577 else
578 s.release(3);
579 }
580 awaitTermination(t);
581 assertEquals(0, s.availablePermits());
582 assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS);
583 }
584
585 /**
586 * fair locks are strictly FIFO
587 */
588 public void testFairLocksFifo() {
589 final PublicSemaphore s = new PublicSemaphore(1, true);
590 final CountDownLatch pleaseRelease = new CountDownLatch(1);
591 Thread t1 = newStartedThread(new CheckedRunnable() {
592 public void realRun() throws InterruptedException {
593 // Will block; permits are available, but not three
594 s.acquire(3);
595 }});
596
597 waitForQueuedThreads(s);
598
599 Thread t2 = newStartedThread(new CheckedRunnable() {
600 public void realRun() throws InterruptedException {
601 // Will fail, even though 1 permit is available
602 assertFalse(s.tryAcquire(0L, MILLISECONDS));
603 assertFalse(s.tryAcquire(1, 0L, MILLISECONDS));
604
605 // untimed tryAcquire will barge and succeed
606 assertTrue(s.tryAcquire());
607 s.release(2);
608 assertTrue(s.tryAcquire(2));
609 s.release();
610
611 pleaseRelease.countDown();
612 // Will queue up behind t1, even though 1 permit is available
613 s.acquire();
614 }});
615
616 await(pleaseRelease);
617 waitForQueuedThread(s, t2);
618 s.release(2);
619 awaitTermination(t1);
620 assertTrue(t2.isAlive());
621 s.release();
622 awaitTermination(t2);
Narayan Kamath8e9a0e92015-04-28 11:40:00 +0100623 }
Calin Juravle8f0d92b2013-08-01 17:26:00 +0100624
625 /**
626 * toString indicates current number of permits
627 */
628 public void testToString() { testToString(false); }
629 public void testToString_fair() { testToString(true); }
630 public void testToString(boolean fair) {
631 PublicSemaphore s = new PublicSemaphore(0, fair);
632 assertTrue(s.toString().contains("Permits = 0"));
633 s.release();
634 assertTrue(s.toString().contains("Permits = 1"));
635 s.release(2);
636 assertTrue(s.toString().contains("Permits = 3"));
637 s.reducePermits(5);
638 assertTrue(s.toString().contains("Permits = -2"));
639 }
640
641}