• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 package jsr166;
10 
11 import static java.util.concurrent.TimeUnit.MILLISECONDS;
12 
13 import java.util.Collection;
14 import java.util.concurrent.CountDownLatch;
15 import java.util.concurrent.Semaphore;
16 
17 import junit.framework.AssertionFailedError;
18 import junit.framework.Test;
19 import junit.framework.TestSuite;
20 
21 public 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     // }
31     /**
32      * Subclass to expose protected methods
33      */
34     static class PublicSemaphore extends Semaphore {
PublicSemaphore(int permits)35         PublicSemaphore(int permits) { super(permits); }
PublicSemaphore(int permits, boolean fair)36         PublicSemaphore(int permits, boolean fair) { super(permits, fair); }
getQueuedThreads()37         public Collection<Thread> getQueuedThreads() {
38             return super.getQueuedThreads();
39         }
hasQueuedThread(Thread t)40         public boolean hasQueuedThread(Thread t) {
41             return super.getQueuedThreads().contains(t);
42         }
reducePermits(int reduction)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;
InterruptibleLockRunnable(Semaphore s)53         InterruptibleLockRunnable(Semaphore s) { lock = s; }
realRun()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;
InterruptedLockRunnable(Semaphore s)67         InterruptedLockRunnable(Semaphore s) { lock = s; }
realRun()68         public void realRun() throws InterruptedException {
69             lock.acquire();
70         }
71     }
72 
73     /**
74      * Spin-waits until s.hasQueuedThread(t) becomes true.
75      */
waitForQueuedThread(PublicSemaphore s, Thread t)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      */
waitForQueuedThreads(Semaphore s)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 {
acquire()100         acquire() {
101             void acquire(Semaphore s) throws InterruptedException {
102                 s.acquire();
103             }
104         },
acquireN()105         acquireN() {
106             void acquire(Semaphore s, int permits) throws InterruptedException {
107                 s.acquire(permits);
108             }
109         },
acquireUninterruptibly()110         acquireUninterruptibly() {
111             void acquire(Semaphore s) {
112                 s.acquireUninterruptibly();
113             }
114         },
acquireUninterruptiblyN()115         acquireUninterruptiblyN() {
116             void acquire(Semaphore s, int permits) {
117                 s.acquireUninterruptibly(permits);
118             }
119         },
tryAcquire()120         tryAcquire() {
121             void acquire(Semaphore s) {
122                 assertTrue(s.tryAcquire());
123             }
124         },
tryAcquireN()125         tryAcquireN() {
126             void acquire(Semaphore s, int permits) {
127                 assertTrue(s.tryAcquire(permits));
128             }
129         },
tryAcquireTimed()130         tryAcquireTimed() {
131             void acquire(Semaphore s) throws InterruptedException {
132                 assertTrue(s.tryAcquire(2 * LONG_DELAY_MS, MILLISECONDS));
133             }
134         },
135         tryAcquireTimedN {
acquire(Semaphore s, int permits)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. */
acquire(Semaphore s)144         void acquire(Semaphore s) throws InterruptedException {
145             acquire(s, 1);
146         }
147         /** Acquires the given number of permits. */
acquire(Semaphore s, int 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      */
testConstructor()157     public void testConstructor()      { testConstructor(false); }
testConstructor_fair()158     public void testConstructor_fair() { testConstructor(true); }
testConstructor(boolean fair)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      */
testConstructorDefaultsToNonFair()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      */
testTryAcquireInSameThread()181     public void testTryAcquireInSameThread()      { testTryAcquireInSameThread(false); }
testTryAcquireInSameThread_fair()182     public void testTryAcquireInSameThread_fair() { testTryAcquireInSameThread(true); }
testTryAcquireInSameThread(boolean fair)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      */
testTryAcquire_timeout()197     public void testTryAcquire_timeout()      { testTryAcquire_timeout(false); }
testTryAcquire_timeout_fair()198     public void testTryAcquire_timeout_fair() { testTryAcquire_timeout(true); }
testTryAcquire_timeout(boolean fair)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      */
testTryAcquireN_timeout()210     public void testTryAcquireN_timeout()      { testTryAcquireN_timeout(false); }
testTryAcquireN_timeout_fair()211     public void testTryAcquireN_timeout_fair() { testTryAcquireN_timeout(true); }
testTryAcquireN_timeout(boolean fair)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      */
testInterruptible_acquire()224     public void testInterruptible_acquire()               { testInterruptible(false, AcquireMethod.acquire); }
testInterruptible_acquire_fair()225     public void testInterruptible_acquire_fair()          { testInterruptible(true,  AcquireMethod.acquire); }
testInterruptible_acquireN()226     public void testInterruptible_acquireN()              { testInterruptible(false, AcquireMethod.acquireN); }
testInterruptible_acquireN_fair()227     public void testInterruptible_acquireN_fair()         { testInterruptible(true,  AcquireMethod.acquireN); }
testInterruptible_tryAcquireTimed()228     public void testInterruptible_tryAcquireTimed()       { testInterruptible(false, AcquireMethod.tryAcquireTimed); }
testInterruptible_tryAcquireTimed_fair()229     public void testInterruptible_tryAcquireTimed_fair()  { testInterruptible(true,  AcquireMethod.tryAcquireTimed); }
testInterruptible_tryAcquireTimedN()230     public void testInterruptible_tryAcquireTimedN()      { testInterruptible(false, AcquireMethod.tryAcquireTimedN); }
testInterruptible_tryAcquireTimedN_fair()231     public void testInterruptible_tryAcquireTimedN_fair() { testInterruptible(true,  AcquireMethod.tryAcquireTimedN); }
testInterruptible(boolean fair, final AcquireMethod acquirer)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      */
testUninterruptible_acquireUninterruptibly()278     public void testUninterruptible_acquireUninterruptibly()       { testUninterruptible(false, AcquireMethod.acquireUninterruptibly); }
testUninterruptible_acquireUninterruptibly_fair()279     public void testUninterruptible_acquireUninterruptibly_fair()  { testUninterruptible(true,  AcquireMethod.acquireUninterruptibly); }
testUninterruptible_acquireUninterruptiblyN()280     public void testUninterruptible_acquireUninterruptiblyN()      { testUninterruptible(false, AcquireMethod.acquireUninterruptiblyN); }
testUninterruptible_acquireUninterruptiblyN_fair()281     public void testUninterruptible_acquireUninterruptiblyN_fair() { testUninterruptible(true,  AcquireMethod.acquireUninterruptiblyN); }
testUninterruptible(boolean fair, final AcquireMethod acquirer)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      */
testHasQueuedThreads()320     public void testHasQueuedThreads()      { testHasQueuedThreads(false); }
testHasQueuedThreads_fair()321     public void testHasQueuedThreads_fair() { testHasQueuedThreads(true); }
testHasQueuedThreads(boolean fair)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      */
testGetQueueLength()343     public void testGetQueueLength()      { testGetQueueLength(false); }
testGetQueueLength_fair()344     public void testGetQueueLength_fair() { testGetQueueLength(true); }
testGetQueueLength(boolean fair)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      */
testGetQueuedThreads()366     public void testGetQueuedThreads()      { testGetQueuedThreads(false); }
testGetQueuedThreads_fair()367     public void testGetQueuedThreads_fair() { testGetQueuedThreads(true); }
testGetQueuedThreads(boolean fair)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      */
testDrainPermits()392     public void testDrainPermits()      { testDrainPermits(false); }
testDrainPermits_fair()393     public void testDrainPermits_fair() { testDrainPermits(true); }
testDrainPermits(boolean fair)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      */
testReleaseIAE()408     public void testReleaseIAE()      { testReleaseIAE(false); }
testReleaseIAE_fair()409     public void testReleaseIAE_fair() { testReleaseIAE(true); }
testReleaseIAE(boolean fair)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      */
testReducePermitsIAE()421     public void testReducePermitsIAE()      { testReducePermitsIAE(false); }
testReducePermitsIAE_fair()422     public void testReducePermitsIAE_fair() { testReducePermitsIAE(true); }
testReducePermitsIAE(boolean fair)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      */
testReducePermits()434     public void testReducePermits()      { testReducePermits(false); }
testReducePermits_fair()435     public void testReducePermits_fair() { testReducePermits(true); }
testReducePermits(boolean fair)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      */
testSerialization()455     public void testSerialization()      { testSerialization(false); }
testSerialization_fair()456     public void testSerialization_fair() { testSerialization(true); }
testSerialization(boolean fair)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      */
testTryAcquireNInSameThread()495     public void testTryAcquireNInSameThread()      { testTryAcquireNInSameThread(false); }
testTryAcquireNInSameThread_fair()496     public void testTryAcquireNInSameThread_fair() { testTryAcquireNInSameThread(true); }
testTryAcquireNInSameThread(boolean fair)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      */
testReleaseAcquireSameThread_acquire()512     public void testReleaseAcquireSameThread_acquire()       { testReleaseAcquireSameThread(false, AcquireMethod.acquire); }
testReleaseAcquireSameThread_acquire_fair()513     public void testReleaseAcquireSameThread_acquire_fair()  { testReleaseAcquireSameThread(true, AcquireMethod.acquire); }
testReleaseAcquireSameThread_acquireN()514     public void testReleaseAcquireSameThread_acquireN()      { testReleaseAcquireSameThread(false, AcquireMethod.acquireN); }
testReleaseAcquireSameThread_acquireN_fair()515     public void testReleaseAcquireSameThread_acquireN_fair() { testReleaseAcquireSameThread(true, AcquireMethod.acquireN); }
testReleaseAcquireSameThread_acquireUninterruptibly()516     public void testReleaseAcquireSameThread_acquireUninterruptibly()       { testReleaseAcquireSameThread(false, AcquireMethod.acquireUninterruptibly); }
testReleaseAcquireSameThread_acquireUninterruptibly_fair()517     public void testReleaseAcquireSameThread_acquireUninterruptibly_fair()  { testReleaseAcquireSameThread(true, AcquireMethod.acquireUninterruptibly); }
testReleaseAcquireSameThread_acquireUninterruptiblyN()518     public void testReleaseAcquireSameThread_acquireUninterruptiblyN()      { testReleaseAcquireSameThread(false, AcquireMethod.acquireUninterruptibly); }
testReleaseAcquireSameThread_acquireUninterruptiblyN_fair()519     public void testReleaseAcquireSameThread_acquireUninterruptiblyN_fair() { testReleaseAcquireSameThread(true, AcquireMethod.acquireUninterruptibly); }
testReleaseAcquireSameThread_tryAcquire()520     public void testReleaseAcquireSameThread_tryAcquire()       { testReleaseAcquireSameThread(false, AcquireMethod.tryAcquire); }
testReleaseAcquireSameThread_tryAcquire_fair()521     public void testReleaseAcquireSameThread_tryAcquire_fair()  { testReleaseAcquireSameThread(true, AcquireMethod.tryAcquire); }
testReleaseAcquireSameThread_tryAcquireN()522     public void testReleaseAcquireSameThread_tryAcquireN()      { testReleaseAcquireSameThread(false, AcquireMethod.tryAcquireN); }
testReleaseAcquireSameThread_tryAcquireN_fair()523     public void testReleaseAcquireSameThread_tryAcquireN_fair() { testReleaseAcquireSameThread(true, AcquireMethod.tryAcquireN); }
testReleaseAcquireSameThread_tryAcquireTimed()524     public void testReleaseAcquireSameThread_tryAcquireTimed()       { testReleaseAcquireSameThread(false, AcquireMethod.tryAcquireTimed); }
testReleaseAcquireSameThread_tryAcquireTimed_fair()525     public void testReleaseAcquireSameThread_tryAcquireTimed_fair()  { testReleaseAcquireSameThread(true, AcquireMethod.tryAcquireTimed); }
testReleaseAcquireSameThread_tryAcquireTimedN()526     public void testReleaseAcquireSameThread_tryAcquireTimedN()      { testReleaseAcquireSameThread(false, AcquireMethod.tryAcquireTimedN); }
testReleaseAcquireSameThread_tryAcquireTimedN_fair()527     public void testReleaseAcquireSameThread_tryAcquireTimedN_fair() { testReleaseAcquireSameThread(true, AcquireMethod.tryAcquireTimedN); }
testReleaseAcquireSameThread(boolean fair, final AcquireMethod acquirer)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      */
testReleaseAcquireDifferentThreads_acquire()544     public void testReleaseAcquireDifferentThreads_acquire()       { testReleaseAcquireDifferentThreads(false, AcquireMethod.acquire); }
testReleaseAcquireDifferentThreads_acquire_fair()545     public void testReleaseAcquireDifferentThreads_acquire_fair()  { testReleaseAcquireDifferentThreads(true, AcquireMethod.acquire); }
testReleaseAcquireDifferentThreads_acquireN()546     public void testReleaseAcquireDifferentThreads_acquireN()      { testReleaseAcquireDifferentThreads(false, AcquireMethod.acquireN); }
testReleaseAcquireDifferentThreads_acquireN_fair()547     public void testReleaseAcquireDifferentThreads_acquireN_fair() { testReleaseAcquireDifferentThreads(true, AcquireMethod.acquireN); }
testReleaseAcquireDifferentThreads_acquireUninterruptibly()548     public void testReleaseAcquireDifferentThreads_acquireUninterruptibly()       { testReleaseAcquireDifferentThreads(false, AcquireMethod.acquireUninterruptibly); }
testReleaseAcquireDifferentThreads_acquireUninterruptibly_fair()549     public void testReleaseAcquireDifferentThreads_acquireUninterruptibly_fair()  { testReleaseAcquireDifferentThreads(true, AcquireMethod.acquireUninterruptibly); }
testReleaseAcquireDifferentThreads_acquireUninterruptiblyN()550     public void testReleaseAcquireDifferentThreads_acquireUninterruptiblyN()      { testReleaseAcquireDifferentThreads(false, AcquireMethod.acquireUninterruptibly); }
testReleaseAcquireDifferentThreads_acquireUninterruptiblyN_fair()551     public void testReleaseAcquireDifferentThreads_acquireUninterruptiblyN_fair() { testReleaseAcquireDifferentThreads(true, AcquireMethod.acquireUninterruptibly); }
testReleaseAcquireDifferentThreads_tryAcquireTimed()552     public void testReleaseAcquireDifferentThreads_tryAcquireTimed()       { testReleaseAcquireDifferentThreads(false, AcquireMethod.tryAcquireTimed); }
testReleaseAcquireDifferentThreads_tryAcquireTimed_fair()553     public void testReleaseAcquireDifferentThreads_tryAcquireTimed_fair()  { testReleaseAcquireDifferentThreads(true, AcquireMethod.tryAcquireTimed); }
testReleaseAcquireDifferentThreads_tryAcquireTimedN()554     public void testReleaseAcquireDifferentThreads_tryAcquireTimedN()      { testReleaseAcquireDifferentThreads(false, AcquireMethod.tryAcquireTimedN); }
testReleaseAcquireDifferentThreads_tryAcquireTimedN_fair()555     public void testReleaseAcquireDifferentThreads_tryAcquireTimedN_fair() { testReleaseAcquireDifferentThreads(true, AcquireMethod.tryAcquireTimedN); }
testReleaseAcquireDifferentThreads(boolean fair, final AcquireMethod acquirer)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);
623     }
624 
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 }
642