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.dbunit.util.concurrent;
015:
016: import org.slf4j.Logger;
017: import org.slf4j.LoggerFactory;
018:
019: /**
020: * Base class for simple, small classes
021: * maintaining single values that are always accessed
022: * and updated under synchronization. Since defining them for only
023: * some types seemed too arbitrary, they exist for all basic types,
024: * although it is hard to imagine uses for some.
025: * <p>
026: * These classes mainly exist so that you do not have to go to the
027: * trouble of writing your own miscellaneous classes and methods
028: * in situations including:
029: * <ul>
030: * <li> When you need or want to offload an instance
031: * variable to use its own synchronization lock.
032: * When these objects are used to replace instance variables, they
033: * should almost always be declared as <code>final</code>. This
034: * helps avoid the need to synchronize just to obtain the reference
035: * to the synchronized variable itself.
036: *
037: * <li> When you need methods such as set, commit, or swap.
038: * Note however that
039: * the synchronization for these variables is <em>independent</em>
040: * of any other synchronization perfromed using other locks.
041: * So, they are not
042: * normally useful when accesses and updates among
043: * variables must be coordinated.
044: * For example, it would normally be a bad idea to make
045: * a Point class out of two SynchronizedInts, even those
046: * sharing a lock.
047: *
048: * <li> When defining <code>static</code> variables. It almost
049: * always works out better to rely on synchronization internal
050: * to these objects, rather than class locks.
051: * </ul>
052: * <p>
053: * While they cannot, by nature, share much code,
054: * all of these classes work in the same way.
055: * <p>
056: * <b>Construction</b> <br>
057: * Synchronized variables are always constructed holding an
058: * initial value of the associated type. Constructors also
059: * establish the lock to use for all methods:
060: * <ul>
061: * <li> By default, each variable uses itself as the
062: * synchronization lock. This is the most common
063: * choice in the most common usage contexts in which
064: * SynchronizedVariables are used to split off
065: * synchronization locks for independent attributes
066: * of a class.
067: * <li> You can specify any other Object to use as the
068: * synchronization lock. This allows you to
069: * use various forms of `slave synchronization'. For
070: * example, a variable that is always associated with a
071: * particular object can use that object's lock.
072: * </ul>
073: * <p>
074: * <b>Update methods</b><br>
075: * Each class supports several kinds of update methods:
076: * <ul>
077: * <li> A <code>set</code> method that sets to a new value and returns
078: * previous value. For example, for a SynchronizedBoolean b,
079: * <code>boolean old = b.set(true)</code> performs a test-and-set.
080: * <p>
081: * <li> A <code>commit</code> method that sets to new value only
082: * if currently holding a given value.
083: *
084: * For example, here is a class that uses an optimistic update
085: * loop to recompute a count variable represented as a
086: * SynchronizedInt.
087: * <pre>
088: * class X {
089: * private final SynchronizedInt count = new SynchronizedInt(0);
090: *
091: * static final int MAX_RETRIES = 1000;
092: *
093: * public boolean recomputeCount() throws InterruptedException {
094: * for (int i = 0; i < MAX_RETRIES; ++i) {
095: * int current = count.get();
096: * int next = compute(current);
097: * if (count.commit(current, next))
098: * return true;
099: * 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 &= 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>]
180: **/
181:
182: public class SynchronizedVariable implements Executor {
183:
184: /**
185: * Logger for this class
186: */
187: private static final Logger logger = LoggerFactory
188: .getLogger(SynchronizedVariable.class);
189:
190: protected final Object lock_;
191:
192: /** Create a SynchronizedVariable using the supplied lock **/
193: public SynchronizedVariable(Object lock) {
194: lock_ = lock;
195: }
196:
197: /** Create a SynchronizedVariable using itself as the lock **/
198: public SynchronizedVariable() {
199: lock_ = this ;
200: }
201:
202: /**
203: * Return the lock used for all synchronization for this object
204: **/
205: public Object getLock() {
206: logger.debug("getLock() - start");
207: return lock_;
208: }
209:
210: /**
211: * If current thread is not interrupted, execute the given command
212: * within this object's lock
213: **/
214:
215: public void execute(Runnable command) throws InterruptedException {
216: logger.debug("execute(command=" + command + ") - start");
217:
218: if (Thread.interrupted())
219: throw new InterruptedException();
220: synchronized (lock_) {
221: command.run();
222: }
223: }
224: }
|