1 /*
2 * Atlassian Source Code Template.
3 * User: Mike Cannon-Brookes
4 * Date: 31/07/2002
5 * Time: 19:33:40
6 * CVS Revision: $Revision: 1.1 $
7 * Last CVS Commit: $Date: 2002/12/02 05:26:32 $
8 * Author of last CVS Commit: $Author: mike $
9 *
10 * Originally written by Doug Lea and released into the public domain.
11 * This may be used for any purposes whatsoever without acknowledgment.
12 * Thanks for the assistance and support of Sun Microsystems Labs,
13 * and everyone contributing, testing, and using this code.
14 *
15 * History:
16 * Date Who What
17 * 11Jun1998 dl Create public version
18 * 5Aug1998 dl replaced int counters with longs
19 * 24Aug1999 dl release(n): screen arguments
20 * 31Jul2002 mcb borrowed from Jive 2.5.4(license above says we can do this)
21 */
22 package com.atlassian.core.util;
23
24
25 /**
26 * Base class for counting semaphores.
27 * Conceptually, a semaphore maintains a set of permits.
28 * Each acquire() blocks if necessary
29 * until a permit is available, and then takes it.
30 * Each release adds a permit. However, no actual permit objects
31 * are used; the Semaphore just keeps a count of the number
32 * available and acts accordingly.
33 * <p>
34 * A semaphore initialized to 1 can serve as a mutual exclusion
35 * lock.
36 * <p>
37 * Different implementation subclasses may provide different
38 * ordering guarantees (or lack thereof) surrounding which
39 * threads will be resumed upon a signal.
40 * <p>
41 * The default implementation makes NO
42 * guarantees about the order in which threads will
43 * acquire permits. It is often faster than other implementations.
44 */
45 public class Semaphore
46 {
47
48 /** current number of available permits **/
49 protected long permits;
50
51 /**
52 * Create a Semaphore with the given initial number of permits.
53 * Using a seed of one makes the semaphore act as a mutual exclusion lock.
54 * Negative seeds are also allowed, in which case no acquires will proceed
55 * until the number of releases has pushed the number of permits past 0.
56 */
57 public Semaphore(long initialPermits)
58 {
59 permits = initialPermits;
60 }
61
62
63 /**
64 * Wait until a permit is available, and take one
65 */
66 public void acquire() throws InterruptedException
67 {
68 if (Thread.interrupted())
69 {
70 throw new InterruptedException();
71 }
72
73 synchronized (this)
74 {
75 try
76 {
77 while (permits <= 0)
78 {
79 wait();
80 }
81 --permits;
82 }
83 catch (InterruptedException ex)
84 {
85 notify();
86 throw ex;
87 }
88 }
89 }
90
91 /**
92 * Wait at most msecs millisconds for a permit.
93 */
94 public boolean attempt(long msecs) throws InterruptedException
95 {
96 if (Thread.interrupted())
97 {
98 throw new InterruptedException();
99 }
100
101 synchronized (this)
102 {
103 if (permits > 0)
104 {
105 --permits;
106 return true;
107 }
108 else if (msecs <= 0)
109 {
110 return false;
111 }
112 else
113 {
114 try
115 {
116 long startTime = System.currentTimeMillis();
117 long waitTime = msecs;
118
119 for (; ;)
120 {
121 wait(waitTime);
122 if (permits > 0)
123 {
124 --permits;
125 return true;
126 }
127 else
128 {
129 waitTime = msecs - (System.currentTimeMillis() - startTime);
130 if (waitTime <= 0)
131 {
132 return false;
133 }
134 }
135 }
136 }
137 catch (InterruptedException ex)
138 {
139 notify();
140 throw ex;
141 }
142 }
143 }
144 }
145
146 /**
147 * Release a permit
148 */
149 public synchronized void release()
150 {
151 ++permits;
152 notify();
153 }
154
155
156 /**
157 * Release N permits. <code>release(n)</code> is
158 * equivalent in effect to:
159 * <pre>
160 * for (int i = 0; i < n; ++i) release();
161 * </pre>
162 * <p>
163 * But may be more efficient in some semaphore implementations.
164 *
165 * @exception IllegalArgumentException if n is negative.
166 */
167 public synchronized void release(long n)
168 {
169 if (n < 0)
170 {
171 throw new IllegalArgumentException("Negative argument");
172 }
173
174 permits += n;
175
176 for (long i = 0; i < n; ++i)
177 {
178 notify();
179 }
180 }
181
182 /**
183 * Return the current number of available permits.
184 * Returns an accurate, but possibly unstable value,
185 * that may change immediately after returning.
186 */
187 public synchronized long permits()
188 {
189 return permits;
190 }
191 }