Source for java.util.concurrent.atomic.AtomicMarkableReference

   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: }