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