View Javadoc

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