comparison src/EDU/oswego/cs/dl/util/concurrent/SynchronizedVariable.java @ 0:3dc0c5604566

Initial checkin of blitz 2.0 fcs - no installer yet.
author Dan Creswell <dan.creswell@gmail.com>
date Sat, 21 Mar 2009 11:00:06 +0000
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:3dc0c5604566
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 EDU.oswego.cs.dl.util.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 }