KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > logicalcobwebs > concurrent > SynchronizedVariable


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.logicalcobwebs.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 JavaDoc lock_;
182
183     /** Create a SynchronizedVariable using the supplied lock **/
184     public SynchronizedVariable(Object JavaDoc lock) {
185         lock_ = lock;
186     }
187
188     /** Create a SynchronizedVariable using itself as the lock **/
189     public SynchronizedVariable() {
190         lock_ = this;
191     }
192
193     /**
194      * Return the lock used for all synchronization for this object
195      **/

196     public Object JavaDoc getLock() {
197         return lock_;
198     }
199
200     /**
201      * If current thread is not interrupted, execute the given command
202      * within this object's lock
203      **/

204
205     public void execute(Runnable JavaDoc command) throws InterruptedException JavaDoc {
206         if (Thread.interrupted()) throw new InterruptedException JavaDoc();
207         synchronized (lock_) {
208             command.run();
209         }
210     }
211 }
212
Popular Tags