1. /*
  2. * @(#)AtomicReferenceFieldUpdater.java 1.7 04/03/29
  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. import sun.misc.Unsafe;
  9. import java.lang.reflect.*;
  10. /**
  11. * A reflection-based utility that enables atomic updates to
  12. * designated <tt>volatile</tt> reference fields of designated
  13. * classes. This class is designed for use in atomic data structures
  14. * in which several reference fields of the same node are
  15. * independently subject to atomic updates. For example, a tree node
  16. * might be declared as
  17. *
  18. * <pre>
  19. * class Node {
  20. * private volatile Node left, right;
  21. *
  22. * private static final AtomicReferenceFieldUpdater<Node, Node> leftUpdater =
  23. * AtomicReferenceFieldUpdater.newUpdater(Node.class, Node.class, "left");
  24. * private static AtomicReferenceFieldUpdater<Node, Node> rightUpdater =
  25. * AtomicReferenceFieldUpdater.newUpdater(Node.class, Node.class, "right");
  26. *
  27. * Node getLeft() { return left; }
  28. * boolean compareAndSetLeft(Node expect, Node update) {
  29. * return leftUpdater.compareAndSet(this, expect, update);
  30. * }
  31. * // ... and so on
  32. * }
  33. * </pre>
  34. *
  35. * <p> Note that the guarantees of the <tt>compareAndSet</tt>
  36. * method in this class are weaker than in other atomic classes. Because this
  37. * class cannot ensure that all uses of the field are appropriate for
  38. * purposes of atomic access, it can guarantee atomicity and volatile
  39. * semantics only with respect to other invocations of
  40. * <tt>compareAndSet</tt> and <tt>set</tt>.
  41. * @since 1.5
  42. * @author Doug Lea
  43. * @param <T> The type of the object holding the updatable field
  44. * @param <V> The type of the field
  45. */
  46. public abstract class AtomicReferenceFieldUpdater<T, V> {
  47. /**
  48. * Creates an updater for objects with the given field. The Class
  49. * arguments are needed to check that reflective types and generic
  50. * types match.
  51. * @param tclass the class of the objects holding the field.
  52. * @param vclass the class of the field
  53. * @param fieldName the name of the field to be updated.
  54. * @return the updater
  55. * @throws IllegalArgumentException if the field is not a volatile reference type.
  56. * @throws RuntimeException with a nested reflection-based
  57. * exception if the class does not hold field or is the wrong type.
  58. */
  59. public static <U, W> AtomicReferenceFieldUpdater<U,W> newUpdater(Class<U> tclass, Class<W> vclass, String fieldName) {
  60. // Currently rely on standard intrinsics implementation
  61. return new AtomicReferenceFieldUpdaterImpl<U,W>(tclass,
  62. vclass,
  63. fieldName);
  64. }
  65. /**
  66. * Protected do-nothing constructor for use by subclasses.
  67. */
  68. protected AtomicReferenceFieldUpdater() {
  69. }
  70. /**
  71. * Atomically set the value of the field of the given object managed
  72. * by this Updater to the given updated value if the current value
  73. * <tt>==</tt> the expected value. This method is guaranteed to be
  74. * atomic with respect to other calls to <tt>compareAndSet</tt> and
  75. * <tt>set</tt>, but not necessarily with respect to other
  76. * changes in the field.
  77. * @param obj An object whose field to conditionally set
  78. * @param expect the expected value
  79. * @param update the new value
  80. * @return true if successful.
  81. */
  82. public abstract boolean compareAndSet(T obj, V expect, V update);
  83. /**
  84. * Atomically set the value of the field of the given object managed
  85. * by this Updater to the given updated value if the current value
  86. * <tt>==</tt> the expected value. This method is guaranteed to be
  87. * atomic with respect to other calls to <tt>compareAndSet</tt> and
  88. * <tt>set</tt>, but not necessarily with respect to other
  89. * changes in the field, and may fail spuriously.
  90. * @param obj An object whose field to conditionally set
  91. * @param expect the expected value
  92. * @param update the new value
  93. * @return true if successful.
  94. */
  95. public abstract boolean weakCompareAndSet(T obj, V expect, V update);
  96. /**
  97. * Set the field of the given object managed by this updater. This
  98. * operation is guaranteed to act as a volatile store with respect
  99. * to subsequent invocations of <tt>compareAndSet</tt>.
  100. * @param obj An object whose field to set
  101. * @param newValue the new value
  102. */
  103. public abstract void set(T obj, V newValue);
  104. /**
  105. * Get the current value held in the field by the given object.
  106. * @param obj An object whose field to get
  107. * @return the current value
  108. */
  109. public abstract V get(T obj);
  110. /**
  111. * Set to the given value and return the old value.
  112. *
  113. * @param obj An object whose field to get and set
  114. * @param newValue the new value
  115. * @return the previous value
  116. */
  117. public V getAndSet(T obj, V newValue) {
  118. for (;;) {
  119. V current = get(obj);
  120. if (compareAndSet(obj, current, newValue))
  121. return current;
  122. }
  123. }
  124. /**
  125. * Standard hotspot implementation using intrinsics
  126. */
  127. private static class AtomicReferenceFieldUpdaterImpl<T,V> extends AtomicReferenceFieldUpdater<T,V> {
  128. private static final Unsafe unsafe = Unsafe.getUnsafe();
  129. private final long offset;
  130. private final Class<T> tclass;
  131. private final Class<V> vclass;
  132. AtomicReferenceFieldUpdaterImpl(Class<T> tclass, Class<V> vclass, String fieldName) {
  133. Field field = null;
  134. Class fieldClass = null;
  135. try {
  136. field = tclass.getDeclaredField(fieldName);
  137. fieldClass = field.getType();
  138. } catch(Exception ex) {
  139. throw new RuntimeException(ex);
  140. }
  141. if (vclass != fieldClass)
  142. throw new ClassCastException();
  143. if (!Modifier.isVolatile(field.getModifiers()))
  144. throw new IllegalArgumentException("Must be volatile type");
  145. this.tclass = tclass;
  146. this.vclass = vclass;
  147. offset = unsafe.objectFieldOffset(field);
  148. }
  149. public boolean compareAndSet(T obj, V expect, V update) {
  150. if (!tclass.isInstance(obj) ||
  151. (update != null && !vclass.isInstance(update)))
  152. throw new ClassCastException();
  153. return unsafe.compareAndSwapObject(obj, offset, expect, update);
  154. }
  155. public boolean weakCompareAndSet(T obj, V expect, V update) {
  156. // same implementation as strong form for now
  157. if (!tclass.isInstance(obj) ||
  158. (update != null && !vclass.isInstance(update)))
  159. throw new ClassCastException();
  160. return unsafe.compareAndSwapObject(obj, offset, expect, update);
  161. }
  162. public void set(T obj, V newValue) {
  163. if (!tclass.isInstance(obj) ||
  164. (newValue != null && !vclass.isInstance(newValue)))
  165. throw new ClassCastException();
  166. unsafe.putObjectVolatile(obj, offset, newValue);
  167. }
  168. public V get(T obj) {
  169. if (!tclass.isInstance(obj))
  170. throw new ClassCastException();
  171. return (V)unsafe.getObjectVolatile(obj, offset);
  172. }
  173. }
  174. }