View Javadoc
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 org.dbunit.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  * 
255  * <p>[<a href="http://gee.cs.oswego.edu/dl/classes/EDU/oswego/cs/dl/util/concurrent/intro.html"> Introduction to this package. </a>]</p>
256  * 
257  * @author Doug Lea
258  * @author Last changed by: $Author$
259  * @version $Revision$ $Date$
260  * @since ? (pre 2.1)
261  */
262 public interface Sync {
263 
264   /** 
265    *  Wait (possibly forever) until successful passage.
266    *  Fail only upon interuption. Interruptions always result in
267    *  `clean' failures. On failure,  you can be sure that it has not 
268    *  been acquired, and that no 
269    *  corresponding release should be performed. Conversely,
270    *  a normal return guarantees that the acquire was successful.
271   **/
272 
273   public void acquire() throws InterruptedException;
274 
275   /** 
276    * Wait at most msecs to pass; report whether passed.
277    * <p>
278    * The method has best-effort semantics:
279    * The msecs bound cannot
280    * be guaranteed to be a precise upper bound on wait time in Java.
281    * Implementations generally can only attempt to return as soon as possible
282    * after the specified bound. Also, timers in Java do not stop during garbage
283    * collection, so timeouts can occur just because a GC intervened.
284    * So, msecs arguments should be used in
285    * a coarse-grained manner. Further,
286    * implementations cannot always guarantee that this method
287    * will return at all without blocking indefinitely when used in
288    * unintended ways. For example, deadlocks may be encountered
289    * when called in an unintended context.
290    * <p>
291    * @param msecs the number of milleseconds to wait.
292    * An argument less than or equal to zero means not to wait at all. 
293    * However, this may still require
294    * access to a synchronization lock, which can impose unbounded
295    * delay if there is a lot of contention among threads.
296    * @return true if acquired
297   **/
298 
299   public boolean attempt(long msecs) throws InterruptedException;
300 
301   /** 
302    * Potentially enable others to pass.
303    * <p>
304    * Because release does not raise exceptions, 
305    * it can be used in `finally' clauses without requiring extra
306    * embedded try/catch blocks. But keep in mind that
307    * as with any java method, implementations may 
308    * still throw unchecked exceptions such as Error or NullPointerException
309    * when faced with uncontinuable errors. However, these should normally
310    * only be caught by higher-level error handlers.
311   **/
312 
313   public void release();
314 
315   /**  One second, in milliseconds; convenient as a time-out value **/
316   public static final long ONE_SECOND = 1000;
317 
318   /**  One minute, in milliseconds; convenient as a time-out value **/
319   public static final long ONE_MINUTE = 60 * ONE_SECOND;
320 
321   /**  One hour, in milliseconds; convenient as a time-out value **/
322   public static final long ONE_HOUR = 60 * ONE_MINUTE;
323 
324   /**  One day, in milliseconds; convenient as a time-out value **/
325   public static final long ONE_DAY = 24 * ONE_HOUR;
326 
327   /**  One week, in milliseconds; convenient as a time-out value **/
328   public static final long ONE_WEEK = 7 * ONE_DAY;
329 
330   /**  One year in milliseconds; convenient as a time-out value  **/
331   // Not that it matters, but there is some variation across
332   // standard sources about value at msec precision.
333   // The value used is the same as in java.util.GregorianCalendar
334   public static final long ONE_YEAR = (long)(365.2425 * ONE_DAY);
335 
336   /**  One century in milliseconds; convenient as a time-out value **/
337   public static final long ONE_CENTURY = 100 * ONE_YEAR;
338 
339 
340 }
341 
342