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