View Javadoc
1   /*
2     File: SynchronizedVariable.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    30Jun1998  dl               Create public version
12  */
13  
14  package org.dbunit.util.concurrent;
15  
16  import org.slf4j.Logger;
17  import org.slf4j.LoggerFactory;
18  
19  /**
20   * Base class for simple,  small classes 
21   * maintaining single values that are always accessed
22   * and updated under synchronization. Since defining them for only
23   * some types seemed too arbitrary, they exist for all basic types,
24   * although it is hard to imagine uses for some.
25   * <p>
26   *   These classes mainly exist so that you do not have to go to the
27   *   trouble of writing your own miscellaneous classes and methods
28   *   in situations  including:
29   *  <ul>
30   *   <li> When  you need or want to offload an instance 
31   *    variable to use its own synchronization lock.
32   *    When these objects are used to replace instance variables, they
33   *    should almost always be declared as <code>final</code>. This
34   *    helps avoid the need to synchronize just to obtain the reference
35   *    to the synchronized variable itself.
36   *
37   *    <li> When you need methods such as set, commit, or swap.
38   *    Note however that
39   *    the synchronization for these variables is <em>independent</em>
40   *    of any other synchronization perfromed using other locks. 
41   *    So, they are not
42   *    normally useful when accesses and updates among 
43   *    variables must be coordinated.
44   *    For example, it would normally be a bad idea to make
45   *    a Point class out of two SynchronizedInts, even those
46   *    sharing a lock.
47   *
48   *    <li> When defining <code>static</code> variables. It almost
49   *    always works out better to rely on synchronization internal
50   *    to these objects, rather  than class locks.
51   *  </ul>
52   * <p>
53   * While they cannot, by nature, share much code,
54   * all of these classes work in the same way.
55   * <p>
56   * <b>Construction</b> <br>
57   * Synchronized variables are always constructed holding an
58   * initial value of the associated type. Constructors also
59   * establish the lock to use for all methods:
60   * <ul>
61   *   <li> By default, each variable uses itself as the
62   *        synchronization lock. This is the most common
63   *        choice in the most common usage contexts in which
64   *        SynchronizedVariables are used to split off
65   *        synchronization locks for independent attributes
66   *        of a class.
67   *   <li> You can specify any other Object to use as the
68   *        synchronization lock. This allows you to
69   *        use various forms of `slave synchronization'. For
70   *        example, a variable that is always associated with a
71   *        particular object can use that object's lock.
72   * </ul>
73   * <p>
74   * <b>Update methods</b><br>
75   * Each class supports several kinds of update methods:
76   * <ul>
77   *   <li> A <code>set</code> method that sets to a new value and returns 
78   *    previous value. For example, for a SynchronizedBoolean b,
79   *    <code>boolean old = b.set(true)</code> performs a test-and-set.
80   * <p>
81   *   <li> A  <code>commit</code> method that sets to new value only
82   *    if currently holding a given value.
83   * 
84   * For example, here is a class that uses an optimistic update
85   * loop to recompute a count variable represented as a 
86   * SynchronizedInt. 
87   *  <pre>
88   *  class X {
89   *    private final SynchronizedInt count = new SynchronizedInt(0);
90   * 
91   *    static final int MAX_RETRIES = 1000;
92   *
93   *    public boolean recomputeCount() throws InterruptedException {
94   *      for (int i = 0; i &lt; MAX_RETRIES; ++i) {
95   *        int current = count.get();
96   *        int next = compute(current);
97   *        if (count.commit(current, next))
98   *          return true;
99   *        else if (Thread.interrupted()) 
100  *          throw new InterruptedException();
101  *      }
102  *      return false;
103  *    }
104  *    int compute(int l) { ... some kind of computation ...  }
105  *  }
106  * </pre>
107  * <p>
108  *   <li>A <code>swap</code> method that atomically swaps with another 
109  *    object of the same class using a deadlock-avoidance strategy.
110  * <p>
111  *    <li> Update-in-place methods appropriate to the type. All
112  *    numerical types support:
113  *     <ul>
114  *       <li> add(x) (equivalent to return value += x)
115  *       <li> subtract(x) (equivalent to return value -= x)
116  *       <li> multiply(x) (equivalent to return value *= x)
117  *       <li> divide(x) (equivalent to return value /= x)
118  *     </ul>
119  *   Integral types also support:
120  *     <ul>
121  *       <li> increment() (equivalent to return ++value)
122  *       <li> decrement() (equivalent to return --value)
123  *     </ul>
124  *    Boolean types support:
125  *     <ul>
126  *       <li> or(x) (equivalent to return value |= x)
127  *       <li> and(x) (equivalent to return value &amp;= x)
128  *       <li> xor(x) (equivalent to return value ^= x)
129  *       <li> complement() (equivalent to return x = !x)
130  *     </ul>
131  *    These cover most, but not all of the possible operators in Java.
132  *    You can add more compute-and-set methods in subclasses. This
133  *    is often a good way to avoid the need for ad-hoc synchronized
134  *    blocks surrounding expressions.
135  *  </ul>
136  * <p>
137  * <b>Guarded methods</b> <br>
138  *   All <code>Waitable</code> subclasses provide notifications on
139  *   every value update, and support guarded methods of the form
140  *   <code>when</code><em>predicate</em>, that wait until the
141  *   predicate hold,  then optionally run any Runnable action
142  *   within the lock, and then return. All types support:
143  *     <ul>
144  *       <li> whenEqual(value, action)
145  *       <li> whenNotEqual(value, action)
146  *     </ul>
147  *   (If the action argument is null, these return immediately
148  *   after the predicate holds.)
149  *   Numerical types also support 
150  *     <ul>
151  *       <li> whenLess(value, action)
152  *       <li> whenLessEqual(value, action)
153  *       <li> whenGreater(value, action)
154  *       <li> whenGreaterEqual(value, action)
155  *     </ul>
156  *   The Waitable classes are not always spectacularly efficient since they
157  *   provide notifications on all value changes.  They are
158  *   designed for use in contexts where either performance is not an
159  *   overriding issue, or where nearly every update releases guarded
160  *   waits anyway.
161  *  <p>
162  * <b>Other methods</b> <br>
163  *   This class implements Executor, and provides an <code>execute</code>
164  *   method that runs the runnable within the lock.
165  *   <p>
166  *   All classes except SynchronizedRef and WaitableRef implement
167  *   <code>Cloneable</code> and <code>Comparable</code>.
168  *   Implementations of the corresponding
169  *   methods either use default mechanics, or use methods that closely
170  *   correspond to their java.lang analogs. SynchronizedRef does not
171  *   implement any of these standard interfaces because there are
172  *   many cases where it would not make sense. However, you can
173  *   easily make simple subclasses that add the appropriate declarations.
174  *
175  *  <p>
176  *
177  *
178  *
179  * <p>[<a href="http://gee.cs.oswego.edu/dl/classes/EDU/oswego/cs/dl/util/concurrent/intro.html"> Introduction to this package. </a>]</p>
180  * 
181  * @author Doug Lea
182  * @author Last changed by: $Author$
183  * @version $Revision$ $Date$
184  * @since ? (pre 2.1)
185  */
186 public class SynchronizedVariable implements Executor {
187 
188     /**
189      * Logger for this class
190      */
191     private static final Logger logger = LoggerFactory.getLogger(SynchronizedVariable.class);
192 
193   protected final Object lock_;
194 
195   /** Create a SynchronizedVariable using the supplied lock **/
196   public SynchronizedVariable(Object lock) { lock_ = lock; }
197 
198   /** Create a SynchronizedVariable using itself as the lock **/
199   public SynchronizedVariable() { lock_ = this; }
200 
201   /**
202    * Return the lock used for all synchronization for this object
203    **/
204   public Object getLock() {
205     return lock_;
206   }
207 
208   /**
209    * If current thread is not interrupted, execute the given command 
210    * within this object's lock
211    **/
212 
213   public void execute(Runnable command) throws InterruptedException {
214     logger.debug("execute(command={}) - start", command);
215     if (Thread.interrupted()) throw new InterruptedException();
216     synchronized (lock_) { 
217       command.run();
218     }
219   }
220 }