001: /*
002: File: SynchronizedRef.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: 11Jun1998 dl Create public version
012: */
013:
014: package EDU.oswego.cs.dl.util.concurrent;
015:
016: import java.io.*;
017:
018: /**
019: * A simple class maintaining a single reference variable that
020: * is always accessed and updated under synchronization.
021: * <p>
022: * <p>[<a href="http://gee.cs.oswego.edu/dl/classes/EDU/oswego/cs/dl/util/concurrent/intro.html"> Introduction to this package. </a>]
023: **/
024:
025: public class SynchronizedRef extends SynchronizedVariable {
026: /** The maintained reference **/
027: protected Object value_;
028:
029: /**
030: * Create a SynchronizedRef initially holding the given reference
031: * and using its own internal lock.
032: **/
033: public SynchronizedRef(Object initialValue) {
034: super ();
035: value_ = initialValue;
036: }
037:
038: /**
039: * Make a new SynchronizedRef with the given initial value,
040: * and using the supplied lock.
041: **/
042: public SynchronizedRef(Object initialValue, Object lock) {
043: super (lock);
044: value_ = initialValue;
045: }
046:
047: /**
048: * Return the current value
049: **/
050: public final Object get() {
051: synchronized (lock_) {
052: return value_;
053: }
054: }
055:
056: /**
057: * Set to newValue.
058: * @return the old value
059: **/
060:
061: public Object set(Object newValue) {
062: synchronized (lock_) {
063: Object old = value_;
064: value_ = newValue;
065: return old;
066: }
067: }
068:
069: /**
070: * Set value to newValue only if it is currently assumedValue.
071: * @return true if successful
072: **/
073: public boolean commit(Object assumedValue, Object newValue) {
074: synchronized (lock_) {
075: boolean success = (assumedValue == value_);
076: if (success)
077: value_ = newValue;
078: return success;
079: }
080: }
081:
082: /**
083: * Atomically swap values with another SynchronizedRef.
084: * Uses identityHashCode to avoid deadlock when
085: * two SynchronizedRefs attempt to simultaneously swap with each other.
086: * (Note: Ordering via identyHashCode is not strictly guaranteed
087: * by the language specification to return unique, orderable
088: * values, but in practice JVMs rely on them being unique.)
089: * @return the new value
090: **/
091:
092: public Object swap(SynchronizedRef other) {
093: if (other == this )
094: return get();
095: SynchronizedRef fst = this ;
096: SynchronizedRef snd = other;
097: if (System.identityHashCode(fst) > System.identityHashCode(snd)) {
098: fst = other;
099: snd = this;
100: }
101: synchronized (fst.lock_) {
102: synchronized (snd.lock_) {
103: fst.set(snd.set(fst.get()));
104: return get();
105: }
106: }
107: }
108:
109: }
|