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