Mercurial > hg > blitz_condensed
comparison src/EDU/oswego/cs/dl/util/concurrent/Semaphore.java @ 0:3dc0c5604566
Initial checkin of blitz 2.0 fcs - no installer yet.
author | Dan Creswell <dan.creswell@gmail.com> |
---|---|
date | Sat, 21 Mar 2009 11:00:06 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:3dc0c5604566 |
---|---|
1 /* | |
2 File: Semaphore.java | |
3 | |
4 Originally written by Doug Lea and released into the public domain. | |
5 This may be used for any purposes whatsoever without acknowledgment. | |
6 Thanks for the assistance and support of Sun Microsystems Labs, | |
7 and everyone contributing, testing, and using this code. | |
8 | |
9 History: | |
10 Date Who What | |
11 11Jun1998 dl Create public version | |
12 5Aug1998 dl replaced int counters with longs | |
13 24Aug1999 dl release(n): screen arguments | |
14 */ | |
15 | |
16 package EDU.oswego.cs.dl.util.concurrent; | |
17 | |
18 /** | |
19 * Base class for counting semaphores. | |
20 * Conceptually, a semaphore maintains a set of permits. | |
21 * Each acquire() blocks if necessary | |
22 * until a permit is available, and then takes it. | |
23 * Each release adds a permit. However, no actual permit objects | |
24 * are used; the Semaphore just keeps a count of the number | |
25 * available and acts accordingly. | |
26 * <p> | |
27 * A semaphore initialized to 1 can serve as a mutual exclusion | |
28 * lock. | |
29 * <p> | |
30 * Different implementation subclasses may provide different | |
31 * ordering guarantees (or lack thereof) surrounding which | |
32 * threads will be resumed upon a signal. | |
33 * <p> | |
34 * The default implementation makes NO | |
35 * guarantees about the order in which threads will | |
36 * acquire permits. It is often faster than other implementations. | |
37 * <p> | |
38 * <b>Sample usage.</b> Here is a class that uses a semaphore to | |
39 * help manage access to a pool of items. | |
40 * <pre> | |
41 * class Pool { | |
42 * static final MAX_AVAILABLE = 100; | |
43 * private final Semaphore available = new Semaphore(MAX_AVAILABLE); | |
44 * | |
45 * public Object getItem() throws InterruptedException { // no synch | |
46 * available.acquire(); | |
47 * return getNextAvailableItem(); | |
48 * } | |
49 * | |
50 * public void putItem(Object x) { // no synch | |
51 * if (markAsUnused(x)) | |
52 * available.release(); | |
53 * } | |
54 * | |
55 * // Not a particularly efficient data structure; just for demo | |
56 * | |
57 * protected Object[] items = ... whatever kinds of items being managed | |
58 * protected boolean[] used = new boolean[MAX_AVAILABLE]; | |
59 * | |
60 * protected synchronized Object getNextAvailableItem() { | |
61 * for (int i = 0; i < MAX_AVAILABLE; ++i) { | |
62 * if (!used[i]) { | |
63 * used[i] = true; | |
64 * return items[i]; | |
65 * } | |
66 * } | |
67 * return null; // not reached | |
68 * } | |
69 * | |
70 * protected synchronized boolean markAsUnused(Object item) { | |
71 * for (int i = 0; i < MAX_AVAILABLE; ++i) { | |
72 * if (item == items[i]) { | |
73 * if (used[i]) { | |
74 * used[i] = false; | |
75 * return true; | |
76 * } | |
77 * else | |
78 * return false; | |
79 * } | |
80 * } | |
81 * return false; | |
82 * } | |
83 * | |
84 * } | |
85 *</pre> | |
86 * <p>[<a href="http://gee.cs.oswego.edu/dl/classes/EDU/oswego/cs/dl/util/concurrent/intro.html"> Introduction to this package. </a>] | |
87 **/ | |
88 | |
89 | |
90 public class Semaphore implements Sync { | |
91 /** current number of available permits **/ | |
92 protected long permits_; | |
93 | |
94 /** | |
95 * Create a Semaphore with the given initial number of permits. | |
96 * Using a seed of one makes the semaphore act as a mutual exclusion lock. | |
97 * Negative seeds are also allowed, in which case no acquires will proceed | |
98 * until the number of releases has pushed the number of permits past 0. | |
99 **/ | |
100 public Semaphore(long initialPermits) { permits_ = initialPermits; } | |
101 | |
102 | |
103 /** Wait until a permit is available, and take one **/ | |
104 public void acquire() throws InterruptedException { | |
105 if (Thread.interrupted()) throw new InterruptedException(); | |
106 synchronized(this) { | |
107 try { | |
108 while (permits_ <= 0) wait(); | |
109 --permits_; | |
110 } | |
111 catch (InterruptedException ex) { | |
112 notify(); | |
113 throw ex; | |
114 } | |
115 } | |
116 } | |
117 | |
118 /** Wait at most msecs millisconds for a permit. **/ | |
119 public boolean attempt(long msecs) throws InterruptedException { | |
120 if (Thread.interrupted()) throw new InterruptedException(); | |
121 | |
122 synchronized(this) { | |
123 if (permits_ > 0) { | |
124 --permits_; | |
125 return true; | |
126 } | |
127 else if (msecs <= 0) | |
128 return false; | |
129 else { | |
130 try { | |
131 long startTime = System.currentTimeMillis(); | |
132 long waitTime = msecs; | |
133 | |
134 for (;;) { | |
135 wait(waitTime); | |
136 if (permits_ > 0) { | |
137 --permits_; | |
138 return true; | |
139 } | |
140 else { | |
141 waitTime = msecs - (System.currentTimeMillis() - startTime); | |
142 if (waitTime <= 0) | |
143 return false; | |
144 } | |
145 } | |
146 } | |
147 catch(InterruptedException ex) { | |
148 notify(); | |
149 throw ex; | |
150 } | |
151 } | |
152 } | |
153 } | |
154 | |
155 /** Release a permit **/ | |
156 public synchronized void release() { | |
157 ++permits_; | |
158 notify(); | |
159 } | |
160 | |
161 | |
162 /** | |
163 * Release N permits. <code>release(n)</code> is | |
164 * equivalent in effect to: | |
165 * <pre> | |
166 * for (int i = 0; i < n; ++i) release(); | |
167 * </pre> | |
168 * <p> | |
169 * But may be more efficient in some semaphore implementations. | |
170 * @exception IllegalArgumentException if n is negative. | |
171 **/ | |
172 public synchronized void release(long n) { | |
173 if (n < 0) throw new IllegalArgumentException("Negative argument"); | |
174 | |
175 permits_ += n; | |
176 for (long i = 0; i < n; ++i) notify(); | |
177 } | |
178 | |
179 /** | |
180 * Return the current number of available permits. | |
181 * Returns an accurate, but possibly unstable value, | |
182 * that may change immediately after returning. | |
183 **/ | |
184 public synchronized long permits() { | |
185 return permits_; | |
186 } | |
187 | |
188 } | |
189 |