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