1. /*
  2. * @(#)AtomicIntegerFieldUpdater.java 1.5 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. import sun.misc.Unsafe;
  9. import java.lang.reflect.*;
  10. /**
  11. * A reflection-based utility that enables atomic updates to
  12. * designated <tt>volatile int</tt> fields of designated classes.
  13. * This class is designed for use in atomic data structures in which
  14. * several fields of the same node are independently subject to atomic
  15. * updates.
  16. *
  17. * <p> Note that the guarantees of the <tt>compareAndSet</tt> method
  18. * in this class are weaker than in other atomic classes. Because this
  19. * class cannot ensure that all uses of the field are appropriate for
  20. * purposes of atomic access, it can guarantee atomicity and volatile
  21. * semantics only with respect to other invocations of
  22. * <tt>compareAndSet</tt> and <tt>set</tt>.
  23. * @since 1.5
  24. * @author Doug Lea
  25. * @param <T> The type of the object holding the updatable field
  26. */
  27. public abstract class AtomicIntegerFieldUpdater<T> {
  28. /**
  29. * Creates an updater for objects with the given field. The Class
  30. * argument is needed to check that reflective types and generic
  31. * types match.
  32. * @param tclass the class of the objects holding the field
  33. * @param fieldName the name of the field to be updated.
  34. * @return the updater
  35. * @throws IllegalArgumentException if the field is not a
  36. * volatile integer type.
  37. * @throws RuntimeException with a nested reflection-based
  38. * exception if the class does not hold field or is the wrong type.
  39. */
  40. public static <U> AtomicIntegerFieldUpdater<U> newUpdater(Class<U> tclass, String fieldName) {
  41. return new AtomicIntegerFieldUpdaterImpl<U>(tclass, fieldName);
  42. }
  43. /**
  44. * Protected do-nothing constructor for use by subclasses.
  45. */
  46. protected AtomicIntegerFieldUpdater() {
  47. }
  48. /**
  49. * Atomically set the value of the field of the given object managed
  50. * by this Updater to the given updated value if the current value
  51. * <tt>==</tt> the expected value. This method is guaranteed to be
  52. * atomic with respect to other calls to <tt>compareAndSet</tt> and
  53. * <tt>set</tt>, but not necessarily with respect to other
  54. * changes in the field.
  55. * @param obj An object whose field to conditionally set
  56. * @param expect the expected value
  57. * @param update the new value
  58. * @return true if successful.
  59. * @throws ClassCastException if <tt>obj</tt> is not an instance
  60. * of the class possessing the field established in the constructor.
  61. */
  62. public abstract boolean compareAndSet(T obj, int expect, int update);
  63. /**
  64. * Atomically set the value of the field of the given object managed
  65. * by this Updater to the given updated value if the current value
  66. * <tt>==</tt> the expected value. This method is guaranteed to be
  67. * atomic with respect to other calls to <tt>compareAndSet</tt> and
  68. * <tt>set</tt>, but not necessarily with respect to other
  69. * changes in the field, and may fail spuriously.
  70. * @param obj An object whose field to conditionally set
  71. * @param expect the expected value
  72. * @param update the new value
  73. * @return true if successful.
  74. * @throws ClassCastException if <tt>obj</tt> is not an instance
  75. * of the class possessing the field established in the constructor.
  76. */
  77. public abstract boolean weakCompareAndSet(T obj, int expect, int update);
  78. /**
  79. * Set the field of the given object managed by this updater. This
  80. * operation is guaranteed to act as a volatile store with respect
  81. * to subsequent invocations of <tt>compareAndSet</tt>.
  82. * @param obj An object whose field to set
  83. * @param newValue the new value
  84. */
  85. public abstract void set(T obj, int newValue);
  86. /**
  87. * Get the current value held in the field by the given object.
  88. * @param obj An object whose field to get
  89. * @return the current value
  90. */
  91. public abstract int get(T obj);
  92. /**
  93. * Set to the given value and return the old value.
  94. *
  95. * @param obj An object whose field to get and set
  96. * @param newValue the new value
  97. * @return the previous value
  98. */
  99. public int getAndSet(T obj, int newValue) {
  100. for (;;) {
  101. int current = get(obj);
  102. if (compareAndSet(obj, current, newValue))
  103. return current;
  104. }
  105. }
  106. /**
  107. * Atomically increment by one the current value.
  108. * @param obj An object whose field to get and set
  109. * @return the previous value;
  110. */
  111. public int getAndIncrement(T obj) {
  112. for (;;) {
  113. int current = get(obj);
  114. int next = current + 1;
  115. if (compareAndSet(obj, current, next))
  116. return current;
  117. }
  118. }
  119. /**
  120. * Atomically decrement by one the current value.
  121. * @param obj An object whose field to get and set
  122. * @return the previous value;
  123. */
  124. public int getAndDecrement(T obj) {
  125. for (;;) {
  126. int current = get(obj);
  127. int next = current - 1;
  128. if (compareAndSet(obj, current, next))
  129. return current;
  130. }
  131. }
  132. /**
  133. * Atomically add the given value to current value.
  134. * @param obj An object whose field to get and set
  135. * @param delta the value to add
  136. * @return the previous value;
  137. */
  138. public int getAndAdd(T obj, int delta) {
  139. for (;;) {
  140. int current = get(obj);
  141. int next = current + delta;
  142. if (compareAndSet(obj, current, next))
  143. return current;
  144. }
  145. }
  146. /**
  147. * Atomically increment by one the current value.
  148. * @param obj An object whose field to get and set
  149. * @return the updated value;
  150. */
  151. public int incrementAndGet(T obj) {
  152. for (;;) {
  153. int current = get(obj);
  154. int next = current + 1;
  155. if (compareAndSet(obj, current, next))
  156. return next;
  157. }
  158. }
  159. /**
  160. * Atomically decrement by one the current value.
  161. * @param obj An object whose field to get and set
  162. * @return the updated value;
  163. */
  164. public int decrementAndGet(T obj) {
  165. for (;;) {
  166. int current = get(obj);
  167. int next = current - 1;
  168. if (compareAndSet(obj, current, next))
  169. return next;
  170. }
  171. }
  172. /**
  173. * Atomically add the given value to current value.
  174. * @param obj An object whose field to get and set
  175. * @param delta the value to add
  176. * @return the updated value;
  177. */
  178. public int addAndGet(T obj, int delta) {
  179. for (;;) {
  180. int current = get(obj);
  181. int next = current + delta;
  182. if (compareAndSet(obj, current, next))
  183. return next;
  184. }
  185. }
  186. /**
  187. * Standard hotspot implementation using intrinsics
  188. */
  189. private static class AtomicIntegerFieldUpdaterImpl<T> extends AtomicIntegerFieldUpdater<T> {
  190. private static final Unsafe unsafe = Unsafe.getUnsafe();
  191. private final long offset;
  192. private final Class<T> tclass;
  193. AtomicIntegerFieldUpdaterImpl(Class<T> tclass, String fieldName) {
  194. Field field = null;
  195. try {
  196. field = tclass.getDeclaredField(fieldName);
  197. } catch(Exception ex) {
  198. throw new RuntimeException(ex);
  199. }
  200. Class fieldt = field.getType();
  201. if (fieldt != int.class)
  202. throw new IllegalArgumentException("Must be integer type");
  203. if (!Modifier.isVolatile(field.getModifiers()))
  204. throw new IllegalArgumentException("Must be volatile type");
  205. this.tclass = tclass;
  206. offset = unsafe.objectFieldOffset(field);
  207. }
  208. public boolean compareAndSet(T obj, int expect, int update) {
  209. if (!tclass.isInstance(obj))
  210. throw new ClassCastException();
  211. return unsafe.compareAndSwapInt(obj, offset, expect, update);
  212. }
  213. public boolean weakCompareAndSet(T obj, int expect, int update) {
  214. if (!tclass.isInstance(obj))
  215. throw new ClassCastException();
  216. return unsafe.compareAndSwapInt(obj, offset, expect, update);
  217. }
  218. public void set(T obj, int newValue) {
  219. if (!tclass.isInstance(obj))
  220. throw new ClassCastException();
  221. unsafe.putIntVolatile(obj, offset, newValue);
  222. }
  223. public final int get(T obj) {
  224. if (!tclass.isInstance(obj))
  225. throw new ClassCastException();
  226. return unsafe.getIntVolatile(obj, offset);
  227. }
  228. }
  229. }