Mercurial > hg > blitz_condensed
comparison src/EDU/oswego/cs/dl/util/concurrent/Sync.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: Sync.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 Added some convenient time constants | |
13 */ | |
14 | |
15 package EDU.oswego.cs.dl.util.concurrent; | |
16 | |
17 /** | |
18 * Main interface for locks, gates, and conditions. | |
19 * <p> | |
20 * Sync objects isolate waiting and notification for particular | |
21 * logical states, resource availability, events, and the like that are | |
22 * shared across multiple threads. Use of Syncs sometimes | |
23 * (but by no means always) adds flexibility and efficiency | |
24 * compared to the use of plain java monitor methods | |
25 * and locking, and are sometimes (but by no means always) | |
26 * simpler to program with. | |
27 * <p> | |
28 * | |
29 * Most Syncs are intended to be used primarily (although | |
30 * not exclusively) in before/after constructions such as: | |
31 * <pre> | |
32 * class X { | |
33 * Sync gate; | |
34 * // ... | |
35 * | |
36 * public void m() { | |
37 * try { | |
38 * gate.acquire(); // block until condition holds | |
39 * try { | |
40 * // ... method body | |
41 * } | |
42 * finally { | |
43 * gate.release() | |
44 * } | |
45 * } | |
46 * catch (InterruptedException ex) { | |
47 * // ... evasive action | |
48 * } | |
49 * } | |
50 * | |
51 * public void m2(Sync cond) { // use supplied condition | |
52 * try { | |
53 * if (cond.attempt(10)) { // try the condition for 10 ms | |
54 * try { | |
55 * // ... method body | |
56 * } | |
57 * finally { | |
58 * cond.release() | |
59 * } | |
60 * } | |
61 * } | |
62 * catch (InterruptedException ex) { | |
63 * // ... evasive action | |
64 * } | |
65 * } | |
66 * } | |
67 * </pre> | |
68 * Syncs may be used in somewhat tedious but more flexible replacements | |
69 * for built-in Java synchronized blocks. For example: | |
70 * <pre> | |
71 * class HandSynched { | |
72 * private double state_ = 0.0; | |
73 * private final Sync lock; // use lock type supplied in constructor | |
74 * public HandSynched(Sync l) { lock = l; } | |
75 * | |
76 * public void changeState(double d) { | |
77 * try { | |
78 * lock.acquire(); | |
79 * try { state_ = updateFunction(d); } | |
80 * finally { lock.release(); } | |
81 * } | |
82 * catch(InterruptedException ex) { } | |
83 * } | |
84 * | |
85 * public double getState() { | |
86 * double d = 0.0; | |
87 * try { | |
88 * lock.acquire(); | |
89 * try { d = accessFunction(state_); } | |
90 * finally { lock.release(); } | |
91 * } | |
92 * catch(InterruptedException ex){} | |
93 * return d; | |
94 * } | |
95 * private double updateFunction(double d) { ... } | |
96 * private double accessFunction(double d) { ... } | |
97 * } | |
98 * </pre> | |
99 * If you have a lot of such methods, and they take a common | |
100 * form, you can standardize this using wrappers. Some of these | |
101 * wrappers are standardized in LockedExecutor, but you can make others. | |
102 * For example: | |
103 * <pre> | |
104 * class HandSynchedV2 { | |
105 * private double state_ = 0.0; | |
106 * private final Sync lock; // use lock type supplied in constructor | |
107 * public HandSynchedV2(Sync l) { lock = l; } | |
108 * | |
109 * protected void runSafely(Runnable r) { | |
110 * try { | |
111 * lock.acquire(); | |
112 * try { r.run(); } | |
113 * finally { lock.release(); } | |
114 * } | |
115 * catch (InterruptedException ex) { // propagate without throwing | |
116 * Thread.currentThread().interrupt(); | |
117 * } | |
118 * } | |
119 * | |
120 * public void changeState(double d) { | |
121 * runSafely(new Runnable() { | |
122 * public void run() { state_ = updateFunction(d); } | |
123 * }); | |
124 * } | |
125 * // ... | |
126 * } | |
127 * </pre> | |
128 * <p> | |
129 * One reason to bother with such constructions is to use deadlock- | |
130 * avoiding back-offs when dealing with locks involving multiple objects. | |
131 * For example, here is a Cell class that uses attempt to back-off | |
132 * and retry if two Cells are trying to swap values with each other | |
133 * at the same time. | |
134 * <pre> | |
135 * class Cell { | |
136 * long value; | |
137 * Sync lock = ... // some sync implementation class | |
138 * void swapValue(Cell other) { | |
139 * for (;;) { | |
140 * try { | |
141 * lock.acquire(); | |
142 * try { | |
143 * if (other.lock.attempt(100)) { | |
144 * try { | |
145 * long t = value; | |
146 * value = other.value; | |
147 * other.value = t; | |
148 * return; | |
149 * } | |
150 * finally { other.lock.release(); } | |
151 * } | |
152 * } | |
153 * finally { lock.release(); } | |
154 * } | |
155 * catch (InterruptedException ex) { return; } | |
156 * } | |
157 * } | |
158 * } | |
159 *</pre> | |
160 * <p> | |
161 * Here is an even fancier version, that uses lock re-ordering | |
162 * upon conflict: | |
163 * <pre> | |
164 * class Cell { | |
165 * long value; | |
166 * Sync lock = ...; | |
167 * private static boolean trySwap(Cell a, Cell b) { | |
168 * a.lock.acquire(); | |
169 * try { | |
170 * if (!b.lock.attempt(0)) | |
171 * return false; | |
172 * try { | |
173 * long t = a.value; | |
174 * a.value = b.value; | |
175 * b.value = t; | |
176 * return true; | |
177 * } | |
178 * finally { other.lock.release(); } | |
179 * } | |
180 * finally { lock.release(); } | |
181 * return false; | |
182 * } | |
183 * | |
184 * void swapValue(Cell other) { | |
185 * try { | |
186 * while (!trySwap(this, other) && | |
187 * !tryswap(other, this)) | |
188 * Thread.sleep(1); | |
189 * } | |
190 * catch (InterruptedException ex) { return; } | |
191 * } | |
192 *} | |
193 *</pre> | |
194 * <p> | |
195 * Interruptions are in general handled as early as possible. | |
196 * Normally, InterruptionExceptions are thrown | |
197 * in acquire and attempt(msec) if interruption | |
198 * is detected upon entry to the method, as well as in any | |
199 * later context surrounding waits. | |
200 * However, interruption status is ignored in release(); | |
201 * <p> | |
202 * Timed versions of attempt report failure via return value. | |
203 * If so desired, you can transform such constructions to use exception | |
204 * throws via | |
205 * <pre> | |
206 * if (!c.attempt(timeval)) throw new TimeoutException(timeval); | |
207 * </pre> | |
208 * <p> | |
209 * The TimoutSync wrapper class can be used to automate such usages. | |
210 * <p> | |
211 * All time values are expressed in milliseconds as longs, which have a maximum | |
212 * value of Long.MAX_VALUE, or almost 300,000 centuries. It is not | |
213 * known whether JVMs actually deal correctly with such extreme values. | |
214 * For convenience, some useful time values are defined as static constants. | |
215 * <p> | |
216 * All implementations of the three Sync methods guarantee to | |
217 * somehow employ Java <code>synchronized</code> methods or blocks, | |
218 * and so entail the memory operations described in JLS | |
219 * chapter 17 which ensure that variables are loaded and flushed | |
220 * within before/after constructions. | |
221 * <p> | |
222 * Syncs may also be used in spinlock constructions. Although | |
223 * it is normally best to just use acquire(), various forms | |
224 * of busy waits can be implemented. For a simple example | |
225 * (but one that would probably never be preferable to using acquire()): | |
226 * <pre> | |
227 * class X { | |
228 * Sync lock = ... | |
229 * void spinUntilAcquired() throws InterruptedException { | |
230 * // Two phase. | |
231 * // First spin without pausing. | |
232 * int purespins = 10; | |
233 * for (int i = 0; i < purespins; ++i) { | |
234 * if (lock.attempt(0)) | |
235 * return true; | |
236 * } | |
237 * // Second phase - use timed waits | |
238 * long waitTime = 1; // 1 millisecond | |
239 * for (;;) { | |
240 * if (lock.attempt(waitTime)) | |
241 * return true; | |
242 * else | |
243 * waitTime = waitTime * 3 / 2 + 1; // increase 50% | |
244 * } | |
245 * } | |
246 * } | |
247 * </pre> | |
248 * <p> | |
249 * In addition pure synchronization control, Syncs | |
250 * may be useful in any context requiring before/after methods. | |
251 * For example, you can use an ObservableSync | |
252 * (perhaps as part of a LayeredSync) in order to obtain callbacks | |
253 * before and after each method invocation for a given class. | |
254 * <p> | |
255 | |
256 * <p>[<a href="http://gee.cs.oswego.edu/dl/classes/EDU/oswego/cs/dl/util/concurrent/intro.html"> Introduction to this package. </a>] | |
257 **/ | |
258 | |
259 | |
260 public interface Sync { | |
261 | |
262 /** | |
263 * Wait (possibly forever) until successful passage. | |
264 * Fail only upon interuption. Interruptions always result in | |
265 * `clean' failures. On failure, you can be sure that it has not | |
266 * been acquired, and that no | |
267 * corresponding release should be performed. Conversely, | |
268 * a normal return guarantees that the acquire was successful. | |
269 **/ | |
270 | |
271 public void acquire() throws InterruptedException; | |
272 | |
273 /** | |
274 * Wait at most msecs to pass; report whether passed. | |
275 * <p> | |
276 * The method has best-effort semantics: | |
277 * The msecs bound cannot | |
278 * be guaranteed to be a precise upper bound on wait time in Java. | |
279 * Implementations generally can only attempt to return as soon as possible | |
280 * after the specified bound. Also, timers in Java do not stop during garbage | |
281 * collection, so timeouts can occur just because a GC intervened. | |
282 * So, msecs arguments should be used in | |
283 * a coarse-grained manner. Further, | |
284 * implementations cannot always guarantee that this method | |
285 * will return at all without blocking indefinitely when used in | |
286 * unintended ways. For example, deadlocks may be encountered | |
287 * when called in an unintended context. | |
288 * <p> | |
289 * @param msecs the number of milleseconds to wait. | |
290 * An argument less than or equal to zero means not to wait at all. | |
291 * However, this may still require | |
292 * access to a synchronization lock, which can impose unbounded | |
293 * delay if there is a lot of contention among threads. | |
294 * @return true if acquired | |
295 **/ | |
296 | |
297 public boolean attempt(long msecs) throws InterruptedException; | |
298 | |
299 /** | |
300 * Potentially enable others to pass. | |
301 * <p> | |
302 * Because release does not raise exceptions, | |
303 * it can be used in `finally' clauses without requiring extra | |
304 * embedded try/catch blocks. But keep in mind that | |
305 * as with any java method, implementations may | |
306 * still throw unchecked exceptions such as Error or NullPointerException | |
307 * when faced with uncontinuable errors. However, these should normally | |
308 * only be caught by higher-level error handlers. | |
309 **/ | |
310 | |
311 public void release(); | |
312 | |
313 /** One second, in milliseconds; convenient as a time-out value **/ | |
314 public static final long ONE_SECOND = 1000; | |
315 | |
316 /** One minute, in milliseconds; convenient as a time-out value **/ | |
317 public static final long ONE_MINUTE = 60 * ONE_SECOND; | |
318 | |
319 /** One hour, in milliseconds; convenient as a time-out value **/ | |
320 public static final long ONE_HOUR = 60 * ONE_MINUTE; | |
321 | |
322 /** One day, in milliseconds; convenient as a time-out value **/ | |
323 public static final long ONE_DAY = 24 * ONE_HOUR; | |
324 | |
325 /** One week, in milliseconds; convenient as a time-out value **/ | |
326 public static final long ONE_WEEK = 7 * ONE_DAY; | |
327 | |
328 /** One year in milliseconds; convenient as a time-out value **/ | |
329 // Not that it matters, but there is some variation across | |
330 // standard sources about value at msec precision. | |
331 // The value used is the same as in java.util.GregorianCalendar | |
332 public static final long ONE_YEAR = (long)(365.2425 * ONE_DAY); | |
333 | |
334 /** One century in milliseconds; convenient as a time-out value **/ | |
335 public static final long ONE_CENTURY = 100 * ONE_YEAR; | |
336 | |
337 | |
338 } | |
339 | |
340 |