001: /*
002: File: SynchronizedVariable.java
003:
004: Originally written by Doug Lea and released into the public domain.
005: This may be used for any purposes whatsoever without acknowledgment.
006: Thanks for the assistance and support of Sun Microsystems Labs,
007: and everyone contributing, testing, and using this code.
008:
009: History:
010: Date Who What
011: 30Jun1998 dl Create public version
012: */
013:
014: package org.logicalcobwebs.concurrent;
015:
016: /**
017: * Base class for simple, small classes
018: * maintaining single values that are always accessed
019: * and updated under synchronization. Since defining them for only
020: * some types seemed too arbitrary, they exist for all basic types,
021: * although it is hard to imagine uses for some.
022: * <p>
023: * These classes mainly exist so that you do not have to go to the
024: * trouble of writing your own miscellaneous classes and methods
025: * in situations including:
026: * <ul>
027: * <li> When you need or want to offload an instance
028: * variable to use its own synchronization lock.
029: * When these objects are used to replace instance variables, they
030: * should almost always be declared as <code>final</code>. This
031: * helps avoid the need to synchronize just to obtain the reference
032: * to the synchronized variable itself.
033: *
034: * <li> When you need methods such as set, commit, or swap.
035: * Note however that
036: * the synchronization for these variables is <em>independent</em>
037: * of any other synchronization perfromed using other locks.
038: * So, they are not
039: * normally useful when accesses and updates among
040: * variables must be coordinated.
041: * For example, it would normally be a bad idea to make
042: * a Point class out of two SynchronizedInts, even those
043: * sharing a lock.
044: *
045: * <li> When defining <code>static</code> variables. It almost
046: * always works out better to rely on synchronization internal
047: * to these objects, rather than class locks.
048: * </ul>
049: * <p>
050: * While they cannot, by nature, share much code,
051: * all of these classes work in the same way.
052: * <p>
053: * <b>Construction</b> <br>
054: * Synchronized variables are always constructed holding an
055: * initial value of the associated type. Constructors also
056: * establish the lock to use for all methods:
057: * <ul>
058: * <li> By default, each variable uses itself as the
059: * synchronization lock. This is the most common
060: * choice in the most common usage contexts in which
061: * SynchronizedVariables are used to split off
062: * synchronization locks for independent attributes
063: * of a class.
064: * <li> You can specify any other Object to use as the
065: * synchronization lock. This allows you to
066: * use various forms of `slave synchronization'. For
067: * example, a variable that is always associated with a
068: * particular object can use that object's lock.
069: * </ul>
070: * <p>
071: * <b>Update methods</b><br>
072: * Each class supports several kinds of update methods:
073: * <ul>
074: * <li> A <code>set</code> method that sets to a new value and returns
075: * previous value. For example, for a SynchronizedBoolean b,
076: * <code>boolean old = b.set(true)</code> performs a test-and-set.
077: * <p>
078: * <li> A <code>commit</code> method that sets to new value only
079: * if currently holding a given value.
080: *
081: * For example, here is a class that uses an optimistic update
082: * loop to recompute a count variable represented as a
083: * SynchronizedInt.
084: * <pre>
085: * class X {
086: * private final SynchronizedInt count = new SynchronizedInt(0);
087: *
088: * static final int MAX_RETRIES = 1000;
089: *
090: * public boolean recomputeCount() throws InterruptedException {
091: * for (int i = 0; i < MAX_RETRIES; ++i) {
092: * int current = count.get();
093: * int next = compute(current);
094: * if (count.commit(current, next))
095: * return true;
096: * else if (Thread.interrupted())
097: * throw new InterruptedException();
098: * }
099: * 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 &= 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) {
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 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 command) throws InterruptedException {
206: if (Thread.interrupted())
207: throw new InterruptedException();
208: synchronized (lock_) {
209: command.run();
210: }
211: }
212: }
|