GNU Classpath (0.98) | |
Frames | No Frames |
1: /* 2: * Written by Doug Lea with assistance from members of JCP JSR-166 3: * Expert Group and released to the public domain, as explained at 4: * http://creativecommons.org/licenses/publicdomain 5: */ 6: 7: package java.util.concurrent.atomic; 8: 9: /** 10: * An <tt>AtomicStampedReference</tt> maintains an object reference 11: * along with an integer "stamp", that can be updated atomically. 12: * 13: * <p> Implementation note. This implementation maintains stamped 14: * references by creating internal objects representing "boxed" 15: * [reference, integer] pairs. 16: * 17: * @since 1.5 18: * @author Doug Lea 19: * @param <V> The type of object referred to by this reference 20: */ 21: public class AtomicStampedReference<V> { 22: 23: private static class ReferenceIntegerPair<T> { 24: private final T reference; 25: private final int integer; 26: ReferenceIntegerPair(T r, int i) { 27: reference = r; integer = i; 28: } 29: } 30: 31: private final AtomicReference<ReferenceIntegerPair<V>> atomicRef; 32: 33: /** 34: * Creates a new <tt>AtomicStampedReference</tt> with the given 35: * initial values. 36: * 37: * @param initialRef the initial reference 38: * @param initialStamp the initial stamp 39: */ 40: public AtomicStampedReference(V initialRef, int initialStamp) { 41: atomicRef = new AtomicReference<ReferenceIntegerPair<V>> 42: (new ReferenceIntegerPair<V>(initialRef, initialStamp)); 43: } 44: 45: /** 46: * Returns the current value of the reference. 47: * 48: * @return the current value of the reference 49: */ 50: public V getReference() { 51: return atomicRef.get().reference; 52: } 53: 54: /** 55: * Returns the current value of the stamp. 56: * 57: * @return the current value of the stamp 58: */ 59: public int getStamp() { 60: return atomicRef.get().integer; 61: } 62: 63: /** 64: * Returns the current values of both the reference and the stamp. 65: * Typical usage is <tt>int[1] holder; ref = v.get(holder); </tt>. 66: * 67: * @param stampHolder an array of size of at least one. On return, 68: * <tt>stampholder[0]</tt> will hold the value of the stamp. 69: * @return the current value of the reference 70: */ 71: public V get(int[] stampHolder) { 72: ReferenceIntegerPair<V> p = atomicRef.get(); 73: stampHolder[0] = p.integer; 74: return p.reference; 75: } 76: 77: /** 78: * Atomically sets the value of both the reference and stamp 79: * to the given update values if the 80: * current reference is <tt>==</tt> to the expected reference 81: * and the current stamp is equal to the expected stamp. 82: * May fail spuriously and does not provide ordering guarantees, 83: * so is only rarely an appropriate alternative to <tt>compareAndSet</tt>. 84: * 85: * @param expectedReference the expected value of the reference 86: * @param newReference the new value for the reference 87: * @param expectedStamp the expected value of the stamp 88: * @param newStamp the new value for the stamp 89: * @return true if successful 90: */ 91: public boolean weakCompareAndSet(V expectedReference, 92: V newReference, 93: int expectedStamp, 94: int newStamp) { 95: ReferenceIntegerPair<V> current = atomicRef.get(); 96: return expectedReference == current.reference && 97: expectedStamp == current.integer && 98: ((newReference == current.reference && 99: newStamp == current.integer) || 100: atomicRef.weakCompareAndSet(current, 101: new ReferenceIntegerPair<V>(newReference, 102: newStamp))); 103: } 104: 105: /** 106: * Atomically sets the value of both the reference and stamp 107: * to the given update values if the 108: * current reference is <tt>==</tt> to the expected reference 109: * and the current stamp is equal to the expected stamp. 110: * 111: * @param expectedReference the expected value of the reference 112: * @param newReference the new value for the reference 113: * @param expectedStamp the expected value of the stamp 114: * @param newStamp the new value for the stamp 115: * @return true if successful 116: */ 117: public boolean compareAndSet(V expectedReference, 118: V newReference, 119: int expectedStamp, 120: int newStamp) { 121: ReferenceIntegerPair<V> current = atomicRef.get(); 122: return expectedReference == current.reference && 123: expectedStamp == current.integer && 124: ((newReference == current.reference && 125: newStamp == current.integer) || 126: atomicRef.compareAndSet(current, 127: new ReferenceIntegerPair<V>(newReference, 128: newStamp))); 129: } 130: 131: 132: /** 133: * Unconditionally sets the value of both the reference and stamp. 134: * 135: * @param newReference the new value for the reference 136: * @param newStamp the new value for the stamp 137: */ 138: public void set(V newReference, int newStamp) { 139: ReferenceIntegerPair<V> current = atomicRef.get(); 140: if (newReference != current.reference || newStamp != current.integer) 141: atomicRef.set(new ReferenceIntegerPair<V>(newReference, newStamp)); 142: } 143: 144: /** 145: * Atomically sets the value of the stamp to the given update value 146: * if the current reference is <tt>==</tt> to the expected 147: * reference. Any given invocation of this operation may fail 148: * (return <tt>false</tt>) spuriously, but repeated invocation 149: * when the current value holds the expected value and no other 150: * thread is also attempting to set the value will eventually 151: * succeed. 152: * 153: * @param expectedReference the expected value of the reference 154: * @param newStamp the new value for the stamp 155: * @return true if successful 156: */ 157: public boolean attemptStamp(V expectedReference, int newStamp) { 158: ReferenceIntegerPair<V> current = atomicRef.get(); 159: return expectedReference == current.reference && 160: (newStamp == current.integer || 161: atomicRef.compareAndSet(current, 162: new ReferenceIntegerPair<V>(expectedReference, 163: newStamp))); 164: } 165: }
GNU Classpath (0.98) |