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