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>AtomicMarkableReference</tt> maintains an object reference 11: * along with a mark bit, that can be updated atomically. 12: * <p> 13: * <p> Implementation note. This implementation maintains markable 14: * references by creating internal objects representing "boxed" 15: * [reference, boolean] 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 AtomicMarkableReference<V> { 22: 23: private static class ReferenceBooleanPair<T> { 24: private final T reference; 25: private final boolean bit; 26: ReferenceBooleanPair(T r, boolean i) { 27: reference = r; bit = i; 28: } 29: } 30: 31: private final AtomicReference<ReferenceBooleanPair<V>> atomicRef; 32: 33: /** 34: * Creates a new <tt>AtomicMarkableReference</tt> with the given 35: * initial values. 36: * 37: * @param initialRef the initial reference 38: * @param initialMark the initial mark 39: */ 40: public AtomicMarkableReference(V initialRef, boolean initialMark) { 41: atomicRef = new AtomicReference<ReferenceBooleanPair<V>> (new ReferenceBooleanPair<V>(initialRef, initialMark)); 42: } 43: 44: /** 45: * Returns the current value of the reference. 46: * 47: * @return the current value of the reference 48: */ 49: public V getReference() { 50: return atomicRef.get().reference; 51: } 52: 53: /** 54: * Returns the current value of the mark. 55: * 56: * @return the current value of the mark 57: */ 58: public boolean isMarked() { 59: return atomicRef.get().bit; 60: } 61: 62: /** 63: * Returns the current values of both the reference and the mark. 64: * Typical usage is <tt>boolean[1] holder; ref = v.get(holder); </tt>. 65: * 66: * @param markHolder an array of size of at least one. On return, 67: * <tt>markholder[0]</tt> will hold the value of the mark. 68: * @return the current value of the reference 69: */ 70: public V get(boolean[] markHolder) { 71: ReferenceBooleanPair<V> p = atomicRef.get(); 72: markHolder[0] = p.bit; 73: return p.reference; 74: } 75: 76: /** 77: * Atomically sets the value of both the reference and mark 78: * to the given update values if the 79: * current reference is <tt>==</tt> to the expected reference 80: * and the current mark is equal to the expected mark. 81: * May fail spuriously and does not provide ordering guarantees, 82: * so is only rarely an appropriate alternative to <tt>compareAndSet</tt>. 83: * 84: * @param expectedReference the expected value of the reference 85: * @param newReference the new value for the reference 86: * @param expectedMark the expected value of the mark 87: * @param newMark the new value for the mark 88: * @return true if successful 89: */ 90: public boolean weakCompareAndSet(V expectedReference, 91: V newReference, 92: boolean expectedMark, 93: boolean newMark) { 94: ReferenceBooleanPair<V> current = atomicRef.get(); 95: return expectedReference == current.reference && 96: expectedMark == current.bit && 97: ((newReference == current.reference && newMark == current.bit) || 98: atomicRef.weakCompareAndSet(current, 99: new ReferenceBooleanPair<V>(newReference, 100: newMark))); 101: } 102: 103: /** 104: * Atomically sets the value of both the reference and mark 105: * to the given update values if the 106: * current reference is <tt>==</tt> to the expected reference 107: * and the current mark is equal to the expected mark. 108: * 109: * @param expectedReference the expected value of the reference 110: * @param newReference the new value for the reference 111: * @param expectedMark the expected value of the mark 112: * @param newMark the new value for the mark 113: * @return true if successful 114: */ 115: public boolean compareAndSet(V expectedReference, 116: V newReference, 117: boolean expectedMark, 118: boolean newMark) { 119: ReferenceBooleanPair<V> current = atomicRef.get(); 120: return expectedReference == current.reference && 121: expectedMark == current.bit && 122: ((newReference == current.reference && newMark == current.bit) || 123: atomicRef.compareAndSet(current, 124: new ReferenceBooleanPair<V>(newReference, 125: newMark))); 126: } 127: 128: /** 129: * Unconditionally sets the value of both the reference and mark. 130: * 131: * @param newReference the new value for the reference 132: * @param newMark the new value for the mark 133: */ 134: public void set(V newReference, boolean newMark) { 135: ReferenceBooleanPair<V> current = atomicRef.get(); 136: if (newReference != current.reference || newMark != current.bit) 137: atomicRef.set(new ReferenceBooleanPair<V>(newReference, newMark)); 138: } 139: 140: /** 141: * Atomically sets the value of the mark to the given update value 142: * if the current reference is <tt>==</tt> to the expected 143: * reference. Any given invocation of this operation may fail 144: * (return <tt>false</tt>) spuriously, but repeated invocation 145: * when the current value holds the expected value and no other 146: * thread is also attempting to set the value will eventually 147: * succeed. 148: * 149: * @param expectedReference the expected value of the reference 150: * @param newMark the new value for the mark 151: * @return true if successful 152: */ 153: public boolean attemptMark(V expectedReference, boolean newMark) { 154: ReferenceBooleanPair<V> current = atomicRef.get(); 155: return expectedReference == current.reference && 156: (newMark == current.bit || 157: atomicRef.compareAndSet 158: (current, new ReferenceBooleanPair<V>(expectedReference, 159: newMark))); 160: } 161: }
GNU Classpath (0.98) |